CN1790916B - Calibration system for a linearity corrector using filter products - Google Patents
Calibration system for a linearity corrector using filter products Download PDFInfo
- Publication number
- CN1790916B CN1790916B CN 200510137332 CN200510137332A CN1790916B CN 1790916 B CN1790916 B CN 1790916B CN 200510137332 CN200510137332 CN 200510137332 CN 200510137332 A CN200510137332 A CN 200510137332A CN 1790916 B CN1790916 B CN 1790916B
- Authority
- CN
- China
- Prior art keywords
- filter
- order
- frequency
- length
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Expired - Fee Related
Links
Images
Landscapes
- Analogue/Digital Conversion (AREA)
- Compression, Expansion, Code Conversion, And Decoders (AREA)
Abstract
Description
交叉引用 cross reference
本申请要求2004年11月4日提交的申请号为60/625372的美国临时申请的优先权。 This application claims priority to US Provisional Application No. 60/625,372, filed November 4, 2004. the
版权声明 Copyright Notice
依照37 C.E.R.1.71(e),申请人表示,本公开的一部分包含属于和要求版权保护的内容,例如但不限于源码列表、屏幕截图(screen shots)、用户界面、或者用户指令,或者提交的任何其他方面,对这些方面在任何权限中版权保护是或者可能是有用的。本版权所有人对于任何一个专利文件或专利公开文本的传真复制没有异议,例如出现在专利商标局专利文件或记录中。所有其他权利被保留,并且基于本申请或其任何部分的内容、公开显示和公开执行的派生作品的所有其它复制、分发和创建都被适用的版权法所禁止。 Pursuant to 37 C.E.R.1.71(e), applicant represents that a portion of this disclosure contains material that is and claims copyright protection, such as, but not limited to, source code listings, screen shots, user interfaces, or user instructions, or any submitted Other aspects for which copyright protection is or may be useful in any jurisdiction. The copyright owner has no objection to the facsimile reproduction of any of the patent documents or patent disclosures, such as appearing in the Patent and Trademark Office patent files or records. All other rights are reserved and all other reproduction, distribution and creation of derivative works based on the content, public display and public performance of this application or any part thereof are prohibited by applicable copyright laws. the
技术领域 technical field
本发明涉及线性误差校正,尤其涉及一种使用滤波器乘积(filter products)减少或消除由信号处理系统例如模数转换器(ADC)产生的失真的线性校正器。 The present invention relates to linearity error correction, and more particularly to a linearity corrector that uses filter products to reduce or eliminate distortion produced by signal processing systems such as analog-to-digital converters (ADCs). the
背景技术 Background technique
减少ADC所产生的失真增加无寄生动态范围(spurious-free dynamic range)(SFDR),其对于使用ADC来获得数据的系统是有用的,所述系统是例如谱分析器和其他电子测量仪器。 Reducing the distortion produced by the ADC increases spurious-free dynamic range (SFDR), which is useful for systems that use ADCs to acquire data, such as spectrum analyzers and other electronic measurement instruments. the
现代高速ADC设计使用深时钟流水线(deep clock pipeline)来帮助将模拟输入通过一系列改进的步骤精确地转换为采样的数字表示。ADC设计者付出了很大努力来去除模拟处理电路中的明显的非线性源。然而,一般很难去除所有的误差源。设计者试图去除该电路中的最明显的问题直到计算机化建模例如SPICE建模显示该转换器符合技术要求。可以通过使用例如减少非线性装置的动态范围的技术或者使用其周围的反馈来改善线性。然而,一些电路布局具有不能被完全去除的内在失真机制。 Modern high-speed ADC designs use a deep clock pipeline to help accurately convert an analog input into a sampled digital representation in a series of refined steps. ADC designers put a lot of effort into removing significant sources of nonlinearity in the analog processing circuitry. However, it is generally difficult to remove all error sources. Designers try to eliminate the most obvious problems in the circuit until computerized modeling such as SPICE modeling shows that the converter meets specification. Linearity can be improved by using techniques such as reducing the dynamic range of a non-linear device or using feedback around it. However, some circuit topologies have inherent distortion mechanisms that cannot be completely removed. the
流水线处理还为内部数字和模拟电路活动提供对内部模拟信号处理进行调 制的机会。在许多这种情况中,具有自身或其自身衍生物的线性函数的输入信号的自调整产生了残留的非线性失真。这导致了一些难以消除的低水平失真。这种调制可以通过内部电源分配发生。在这种情况下,能够在该电源轨上产生电压调制的电路通道数量可以是相当高。模拟这种效应使得装置建模复杂化并且减缓了计算机模拟。对第一阶来说,对于电源调制的这些影响将会几乎线性增加,所以它们可以作为线性有限脉冲响应(FIR)滤波器建模。 Pipelining also provides the opportunity for internal digital and analog circuit activity to modulate internal analog signal processing. In many such cases, the self-adjustment of the input signal as a linear function of itself or its derivatives produces residual non-linear distortion. This resulted in some low-level distortion that was difficult to remove. This modulation can occur through internal power distribution. In this case, the number of circuit channels capable of producing voltage modulation on that supply rail can be quite high. Simulating this effect complicates device modeling and slows down computer simulations. For the first order, these effects on supply modulation will increase almost linearly, so they can be modeled as linear finite impulse response (FIR) filters. the
在模拟信号处理中的一个或多个点发生调制,其对应于乘法。在流水线ADC中,调制一般发生在转换级之间的高增益模拟放大器中。在这种情况中,典型地该谐波和互调失真的特征在于,存在第2阶和第3阶失真项,其中发生非常少的高阶失真。 Modulation occurs at one or more points in analog signal processing, which correspond to multiplications. In pipeline ADCs, modulation typically occurs in high-gain analog amplifiers between conversion stages. In this case, the harmonic and intermodulation distortion is typically characterized by the presence of 2nd and 3rd order distortion terms, with very little higher order distortion occurring. the
以前提出的解决方案是基于Volterra滤波器的。ADC的脉冲响应可以是许多个时钟周期,例如可以使用64个时钟周期。使用Volterra滤波器的校正系统将需要相似的响应长度。在第3阶失真Volterra系统中,这导致大约(N3)/6抽头的滤波器,其对于具有64响应长度的校正系统将导致大约50000抽头阶。具有这样巨大数量抽头的滤波器系统太复杂和太昂贵以致于当时无法在实际系统中实现。 Previously proposed solutions were based on Volterra filters. The impulse response of the ADC can be many clock periods, for example 64 clock periods can be used. A correction system using a Volterra filter will require a similar response length. In a 3rd order distorted Volterra system, this results in a filter of approximately (N 3 )/6 taps, which for a corrected system with a response length of 64 would result in an order of approximately 50000 taps. Filter systems with such a huge number of taps were too complex and expensive to be realized in practical systems at the time.
在其他与扬声器中的校正失真相关的应用中提出了另一种解决方案,其使用了与Volterra滤波器的某些方面近似的滤波器结构。图1示出了具有第1阶校正和第3阶校正的这种方案的一种型式。第一阶补偿是由滤波器12(h1)来提供的。第三阶补偿是这样提供的,即通过使用乘法器18将滤波器14的输出与滤波器16的输出相乘,使用滤波器20对乘法器18的输出进行过滤,使用乘法器24将滤波器20的输出与滤波器22的输出相乘,最后使用滤波器26对乘法器24的输出进行过滤。通过使用加法器28将来自第一阶补偿的输出和第三阶补偿相加,可以提供线性三次补偿(cubic compensation)。图1中所示系统的第3阶补偿执行下述方程式, Another solution has been proposed in other applications related to correcting distortion in loudspeakers, which uses a filter structure that approximates some aspects of the Volterra filter. Figure 1 shows a version of this scheme with 1st order correction and 3rd order correction. First order compensation is provided by filter 12(h 1 ). Third order compensation is provided by multiplying the output of filter 14 with the output of filter 16 using multiplier 18, filtering the output of multiplier 18 using filter 20, and multiplying the output of filter The output of 20 is multiplied by the output of filter 22 and finally the output of multiplier 24 is filtered using filter 26 . By adding the output from the first order compensation and the third order compensation using adder 28, linear cubic compensation can be provided. The 3rd order compensation for the system shown in Figure 1 implements the following equation,
其被描述为一般的第3阶非线性滤波器结构。这种实现方案在乘法器18之后使用了滤波器20,以及在乘法器24之后的滤波器26。一旦获得该线性三次补 偿,就从正被补偿的该未知系统的输出中减去。这需要该校正器能眵访问输入到该未知系统的原始信号,而当该原始信号不是数字的时候是不可用的。虽然它可以是Volterra滤波器的有用的子方案,但是它也有不适用于具有良好线性频率响应的系统的缺点。紧接在该乘法器之后的滤波器不能区分原始分量和由在先乘法的非线性效应所引起的混叠分量。虽然该乘法器之后的其他滤波可以提供对于信号通道中的频率相关的幅度和相位响应的一些校正,但是当用于使用大部分Nyquist频带的应用中时,混叠不允许该滤波器对该原始分量和混叠分量之间的相位和幅度响应差进行校正。 It is described as a general 3rd order nonlinear filter structure. This implementation uses filter 20 after multiplier 18 and filter 26 after multiplier 24 . Once the linear cubic compensation is obtained, it is subtracted from the output of the unknown system being compensated. This requires that the corrector have full access to the raw signal input to the unknown system, which is not available when the raw signal is not digital. While it can be a useful sub-solution of the Volterra filter, it also has the disadvantage of not being suitable for systems with a good linear frequency response. Filters immediately following this multiplier cannot distinguish between original components and aliased components caused by the nonlinear effects of previous multiplications. While additional filtering after this multiplier can provide some correction to the frequency-dependent magnitude and phase response in the signal path, aliasing does not allow this filter to reproduce the original The phase and magnitude response differences between the aliased and aliased components are corrected for. the
线性补偿系统中的遗留问题涉及校准。这些系统会需要求解相对于该输出成非线性的滤波器系数的系统。对于任何可以应用到该系统的校准方案,求解更多的系数将需要更多的计算量。 A legacy issue in linear compensation systems involves calibration. These systems would require solving a system of filter coefficients that is nonlinear with respect to the output. For any calibration scheme that can be applied to the system, solving for more coefficients will require more computation. the
在现有解决方案上的细节和改进将在以下更加详细地讨论。 Details and improvements over existing solutions are discussed in more detail below. the
发明内容 Contents of the invention
如果可以通过恢复ADC中的等效失真滤波器的系数来对该失真机制建模,该ADC输出就可以通过以基本上相同的方式使该信号失真的数字处理网络,然后,减去该失真以减少或消除该ADC失真。虽然将所有ADC失真完全消除是不可能的,但是本方法改善了ADC的无寄生动态范围(SFDR)。例如,依赖于该ADC的特性,具有SFDR为80dB的ADC可以改进15dB的因子。本改进还从先前提出的布局中去掉了一些滤波器,从而简化了具有相对平滑线性频率响应的系统使用的设计。这种简化可以对校正系统中的更长滤波器交替使用,从而获得具有相同处理量的改进的性能。该改进对于精确测量应用是有意义的,例如那些与频谱分析器、示波器或者其他使用ADC的测量仪器有关的精确测量应用。 If this distortion mechanism can be modeled by recovering the coefficients of an equivalent distortion filter in an ADC, the ADC output can be passed through a digital processing network that distorts the signal in essentially the same way, and then subtracts the distortion to obtain reduce or eliminate this ADC distortion. Although it is impossible to completely eliminate all ADC distortion, this method improves the spurious-free dynamic range (SFDR) of the ADC. For example, an ADC with an SFDR of 80dB can be improved by a factor of 15dB, depending on the characteristics of the ADC. This improvement also removes some filters from the previously proposed layout, thereby simplifying the design for use in systems with a relatively smooth linear frequency response. This simplification can be alternated with longer filters in the correction system, resulting in improved performance with the same throughput. This improvement is of interest for precision measurement applications, such as those associated with spectrum analyzers, oscilloscopes, or other measurement instruments that use ADCs. the
为了实现这些优点,提供一种合适的校准系统和方法。该校准系统包括:产生第一模拟信号的第一模拟信号产生器,产生第二模拟信号的第二模拟信号产生器,以及连接到该第一模拟信号产生器和第二模拟信号产生器的、用于将该第一模拟信号和第二模拟信号相加并提供模拟输出的模拟加法器。该模拟输出被输入到ADC以获得数字输出。将执行对滤波器乘积求和的线性校正器连接到该ADC的数字输出。在正常操作期间,该线性校正器将提供与该ADC的输出相比具有减小的失真的校正输出。将采集存储器连接到该数字输出;并 且将用于控制该第一信号产生器和第二信号产生器的处理器连接以读取该采集存储器数据。还将该处理器连接到该线性校正器以便为该滤波器乘积编程滤波器系数。 To achieve these advantages, a suitable calibration system and method are provided. The calibration system includes: a first analog signal generator that generates a first analog signal, a second analog signal generator that generates a second analog signal, and connected to the first analog signal generator and the second analog signal generator, An analog adder for adding the first and second analog signals and providing an analog output. This analog output is input to an ADC to obtain a digital output. A linearity corrector, which performs a summation of the filter products, is connected to the digital output of the ADC. During normal operation, the linearity corrector will provide a corrected output with reduced distortion compared to the output of the ADC. An acquisition memory is connected to the digital output; and a processor for controlling the first signal generator and the second signal generator is connected to read the acquisition memory data. The processor is also coupled to the linearity corrector for programming filter coefficients for the filter product. the
还提供了一种校准线性校正器的方法。该校准方法通过将第一波形和第二波形输入到具有输出的信号处理系统来完成。当其中每一个从该信号处理系统中输出时,该采集存储器和处理器采集和分析该第一和第二波形的互调和谐波分量。通过基于失真模型以及该互调和谐波分量来确定目标函数的最小值,寻找连接到该装置输出的线性校正器中使用的滤波器的幅度和相位响应。然后,使用该幅度和相位响应来计算一组滤波器系数。 A method of calibrating a linearity corrector is also provided. The calibration method is accomplished by inputting a first waveform and a second waveform to a signal processing system having an output. The acquisition memory and processor acquire and analyze intermodulation and harmonic components of the first and second waveforms as each is output from the signal processing system. By determining the minimum of the objective function based on the distortion model and the intermodulation and harmonic components, the magnitude and phase response of the filter used in the linearity corrector connected to the output of the device is found. This magnitude and phase response is then used to compute a set of filter coefficients. the
附图说明 Description of drawings
图1(现有技术)是用于补偿扬声器的现有技术的线性校正器的布置的框图。 Figure 1 (Prior Art) is a block diagram of an arrangement of a prior art linearity corrector for compensating loudspeakers. the
图2是包括第1阶、第2阶和第3阶失真的补偿的、基于滤波器乘积的线性校正器的框图。 2 is a block diagram of a filter product based linearity corrector including compensation of 1st order, 2nd order and 3rd order distortion. the
图3是包括第1阶和第3阶失真的补偿的、基于滤波器乘积的线性校正器的框图。 Figure 3 is a block diagram of a filter product based linearity corrector including compensation of 1st and 3rd order distortions. the
图4是包括第1阶、第3阶和第4阶失真的补偿的、基于滤波器乘积的线性校正器的框图。 4 is a block diagram of a filter product based linearity corrector including compensation of 1st order, 3rd order and 4th order distortion. the
图5是补偿ADC的框图。 Figure 5 is a block diagram of a compensated ADC. the
图6是包括补偿和校准系统的ADC系统的框图。 Fig. 6 is a block diagram of an ADC system including a compensation and calibration system. the
图7示出了基本校准过程。 Figure 7 shows the basic calibration process. the
图8示出了该校准过程的附加子步骤。 Figure 8 shows additional sub-steps of the calibration process. the
图9示出了该校准过程的附加子步骤。 Figure 9 shows additional sub-steps of the calibration process. the
图10示出了该校准过程的附加子步骤。 Figure 10 shows additional sub-steps of the calibration process. the
具体实施方式 Detailed ways
本说明书包括第21-51页的用于说明本发明的具体实施例的具体实施方式的示例源代码及其注释文件,文件名称是Slavin.txt。 This specification includes pages 21-51 of the example source code and its annotation file for illustrating the specific implementation of the specific embodiment of the present invention, and the file name is Slavin.txt. the
如上所述,在前提出的解决方案基于Volterra滤波器。然而,由于Volterra滤波器非常大并且很难与ADC一起实现,因此,需要一种解决方案,其利用更易管理的滤波器设计,同时还能够减少一些遗留的主要失真。以Volterra滤 波器作为起始点,广义的非线性滤波器系统能够在数学上定义为: As mentioned above, the previously proposed solutions are based on Volterra filters. However, since Volterra filters are very large and difficult to implement with ADCs, a solution is needed that utilizes a more manageable filter design while also reducing some of the remaining major distortions. Taking the Volterra filter as a starting point, a generalized nonlinear filter system can be defined mathematically as:
(方程1) (equation 1)
其中,N是该滤波器的脉冲响应长度,k是该滤波器阶指数(order index)。 Wherein, N is the impulse response length of the filter, and k is the order index of the filter. the
例如,如果n=3,则我们有DC值(h0)、k=1时的线性FIR滤波器项、k=2时的2阶失真滤波器以及k=3时的3阶滤波器的和。因而,对于n=3,该Volterra滤波器可以表示为: For example, if n=3, we have the DC value (h 0 ), the sum of the linear FIR filter term at k=1, the 2nd order distortion filter at k=2 and the 3rd order filter at k=3 . Thus, for n=3, the Volterra filter can be expressed as:
(方程2) (equation 2)
Volterra滤波器系数与输出y是成线性的,所以理论上,可以利用训练数据来找到一组h。一些乘积项刚好是相同组输入采样的置换(permutations),所以对于每个阶指数k在该组h中的区别值的数量由下式给出,该数量对应于滤波器抽头的数量: The Volterra filter coefficients are linear with the output y, so in theory, it is possible to use the training data to find a set of h. Some of the product terms happen to be permutations of the same set of input samples, so for each order index k the number of distinct values in the set h is given by the following equation, which corresponds to the number of filter taps:
(方程3) (Equation 3)
遗憾的是,流水线ADC系统的该脉冲响应会是相当大的,所以N可以很大,对于k=3产生很大数量的抽头。例如,如果该流水线ADC系统的脉冲响应是64个时钟周期,从而N=64,那么所需要的抽头数将是大约44000。附加的抽头被需要用于其他阶滤波器,如果存在的话。 Unfortunately, this impulse response of a pipelined ADC system can be quite large, so N can be very large, resulting in a large number of taps for k=3. For example, if the impulse response of the pipelined ADC system is 64 clock cycles, so that N=64, then the number of taps required will be approximately 44000. Additional taps are needed for other order filters, if present. the
现有的ADC线性校正器的实施例依赖于Volterra滤波器系统的子集。该Volterra滤波器系统的子集的特征在于: Existing embodiments of ADC linearity correctors rely on a subset of the Volterra filter system. A subset of this Volterra filter system is characterized by:
(方程4) (equation 4)
对于1≤k≤n,系统阶n定义了一组乘积阶。 For 1≤k≤n, the system order n defines a set of product orders. the
尽管抽头的数量和值是未知的,但假定失真模型是这种形式。校正模型具有相同的形式,除非基于具有特定ADC构造的实验,事先选择阶和滤波器的长度。校准则包含找出滤波器抽头。注意到,通常滤波器抽头对于每个滤波器 是不同的。对于系统阶n=3,忽略h0(DC)项,我们得到: Although the number and value of taps are unknown, the distortion model is assumed to be of this form. The correction model has the same form, except that the order and filter length are chosen in advance based on experiments with a particular ADC configuration. Calibration involves finding the filter taps. Note that in general the filter taps are different for each filter. For system order n=3, ignoring the h 0 (DC) term, we get:
(方程5) (equation 5)
这种结构的实施例其特征可以在于,具有使用滤波器实现的每个线性卷积的N抽头滤波器的乘积。 Embodiments of such a structure may be characterized as having a product of N-tap filters implemented using filters for each linear convolution. the
图2示出了用于实现方程式5的线性校正器100的实施例。信号处理系统例如ADC的输出作为输入被提供给该线性校正器100。该线性卷积中的每一个,如方程5中所提供的,使用滤波器102到112来实现。该滤波器可以作为FIR滤波器来实现。第一阶项对应于滤波器102。在可选实施例中,通过用近似等于其他滤波器长度的一半的固定延迟代替滤波器102来获得该第一阶项。在另一实施例中,通过用固定延迟和滤波器的组合代替滤波器102来获得该第一阶项,从而使该总延迟近似为其他阶滤波器长度的一半。通过使用乘法器120将滤波器104和滤波器106的输出相乘以产生二阶滤波器乘积来实现第二阶项。通过使用乘法器122将滤波器108、滤波器110和滤波器112的输出相乘以产生三阶滤波器乘积来实现第三阶。然后,使用加法器124将来自滤波器102的输出与乘法器120和乘法器122的输出相加以提供该滤波器乘积的简单和(simple sum)作为输出。这里使用的术语“简单和”表示将该乘法器的值相加而不需在该乘法器和加法器124之间进行额外滤波的操作。这种简单和通过将该乘法器直接连接到加法器来获得。这里使用的术语直接连接(或者直接被连接)的含义是,在该通道上没有滤波器或其它处理元件,在该通道中可以有不改变通道上信号数据的本质特性的寄存器或其他元件。该输出现在是具有由该信号处理系统例如ADC产生的减少了的非线性的补偿信号。应当注意的是,本发明的实施例消除了现有技术的解决方案中提供的、乘法器之后的滤波器。虽然与图1所示现有技术相比这将需要使用具有额外抽头的滤波器,但是它使得能够使用该滤波器补偿某些失真,而不需要来自该乘法器之后的滤波器的额外补偿。例如,如果图1的现有技术使用了一半时钟周期延迟的全通输出滤波器(所谓sm(x)/x或sinc(x)滤波器),则该滤波器可以被结合到该乘法之前的滤波器中。通过仅在乘法器之前使用滤波器,可能的是该滤波器乘积系统就能够 更好地区分原始分量和混叠分量。
FIG. 2 shows an embodiment of a
虽然在一些实施例中可以通过使用不同长度的滤波器来减少计算量,但是更长长度滤波器的使用会增加在校准期间需要求解的变量的数量,这将会使该校准算法变慢。对于硬件实现,更长长度的滤波器也会需要额外的延迟以匹配该滤波信号延迟。因此,在该校正器100的实施例中,所有滤波器长度都相等。
While in some embodiments the amount of computation can be reduced by using filters of different lengths, the use of longer length filters increases the number of variables that need to be resolved during calibration, which slows down the calibration algorithm. For hardware implementations, filters of longer length would also require additional delays to match the filtered signal delay. Therefore, in this embodiment of the
图3示出了设计成用于补偿第1阶和第3阶失真而不补偿第2阶失真的线性校正器100的实施例。在一些应用中,第二阶失真显著不到足以证明包括第2阶补偿是有道理的。如图3所示,通过使用乘法器122将滤波器108、滤波器110和滤波器112的输出相乘以产生第三阶滤波器乘积来提供第三阶补偿。然后该第3阶滤波器乘积和第1阶滤波器乘积的简单和可以提供具有减少或者消除了的第1阶和第3阶失真的补偿信号。
FIG. 3 shows an embodiment of a
如图4所示,能够提供包括第4阶补偿的校正器100的实施例。利用方程4的一般形式,对于系统阶n=4,并且忽略该h0(DC)项,我们就有:
As shown in Figure 4, an embodiment of the
(方程6) (equation 6)
如图4所示,该第4阶项可以通过使用乘法器148将滤波器140、滤波器142、滤波器144和滤波器146一起相乘来执行。此外,使用加法器124将该滤波器乘积与其他阶补偿直接求和,而在该乘法器148和加法器124之间没有任何中间滤波器。如从前面例子中可以清楚的,一个本领域普通技术人员将能够求解方程4,以便针对任何预期阶而将其以与方程5和方程6相似的形式放置,其然后可以如这里一般教导地使用滤波器乘积的简单和来实现。如图4所示,第2阶补偿被去除以考虑如下所详细讨论的校准。这种配置将在第4阶具有较大重要性的那些环境中提供补偿。类似地,能够提供对于第4阶和第5阶的补偿并且消除第2阶和第3阶以考虑如下所述的校准。
As shown in FIG. 4 , this 4th order term may be performed by multiplying
对于所提出的通常的Volterra形式的分解的有效性以及相应的滤波器乘积结构的证明在于理解对于每个乘积阶k存在单一的自调制机制,而不在于任何随机Volterra滤波器系统能够以这种方式被分解的可能性上。 The justification for the validity of the proposed decomposition of the usual Volterra form, and the corresponding filter product structure, lies in the understanding that for each product order k there is a single self-modulation mechanism, not in the fact that any stochastic Volterra filter system is capable of such on the possibility of the way being decomposed.
线性校正器100的各种实施例可以利用专用的硬件执行,例如FPGA或者ASIC,或者利用运行软件的通用处理器执行。当前,尽管运行在通用处理器上的软件对于后采集校正是有用的,但是FPGA或者ASIC对于执行实时校正是有用的。在未来,也有可能为了实时校正利用在通用处理器上的软件。
Various embodiments of
虽然在一些实施例中,该线性校正器100用于补偿从ADC输出的信号,而在其他实施例中,线性校正器100的结构可以集成在与该ADC相同的封装(packing)中,或者可能集成在与该ADC相同的芯片上,以便形成补偿ADC。该补偿ADC190在图5中示出。它包括ADC模块192,该ADC模块192包含将模拟信号转换成数字信号的各种电路。该ADC模块192的数字输出被输入到可以上述教导实现的线性校正器100。该线性校正器的输出是具有减少了失真的补偿输出。这种组合结构提供了补偿ADC。
Although in some embodiments, the
为了适当地优化上述线性校正器,有必要对该线性校正器进行校准以对每个滤波器确定合适的滤波器系数。与一般Volterra滤波器不同,图2-4所示的校正器的滤波器乘积输出不是关于其系数成线性的,所以在一般情况下,该滤波器系数的计算是一个非线性优化问题。 In order to properly optimize the linearity corrector described above, it is necessary to calibrate the linearity corrector to determine appropriate filter coefficients for each filter. Unlike the general Volterra filter, the filter product output of the corrector shown in Figure 2-4 is not linear with respect to its coefficients, so in general, the calculation of the filter coefficients is a nonlinear optimization problem. the
因此,提出了一种具有校准的线性校正器系统和一种校准方法。如图6所示,配备有线性校正器100和校准电路的ADC 200。提供模拟选择开关202以控制进入该ADC的输入。该模拟选择开关202由处理器204控制。在校准期间,处理器204控制该模拟选择开关202以允许校准频率信号进入该ADC 200的输入。处理器204还控制数字选择开关206,以控制在校准期间直接来自该ADC 200的数字输出是否进入采集存储器208。处理器204还控制第一校准频率发生器210和第二校准频率发生器212。在校准期间,该第一校准频率发生器210和第二校准频率发生器212的输出在在输入到ADC 200之前,在求和电路214中组合。在本校准方法的实施例中,进入ADC的该模拟校准信号和模拟求和与该被校准的ADC相比具有显著少的失真。
Therefore, a linearity corrector system with calibration and a calibration method are proposed. As shown in FIG. 6, an
在校准期间,该采集存储器208采集未校正的ADC输出用于校准。处理在校准频率对的范围上多次采集的数据。该采集的数据由处理器204进行处理。
During calibration, the
在正常操作期间,通过模拟选择开关202将该模拟输入输送到ADC 200,并使用该线性校正器100对该ADC的输出进行校正。该校正器的基本操作已经结合图2-4在上面进行了描述。具有该线性校正器的滤波器可以通过处理 器204加载。然后可以使用第二处理器216提供其他处理,例如可以就像对该ADC的直接输出那样处理该校正的输出。图6所示的实施例示出了用于校准和其他处理的采集存储器208。在可选实施例中,可以使用单独的存储器用于其他处理。类似地,图6所示的实施例示出了第二处理器216,在其他实施例中,处理器204能够提供这种额外的处理和控制该校准过程。
During normal operation, the analog input is fed to the
如图7所示,校准线性校正器中的滤波器乘积内的一组滤波器,有四个基本步骤。对于第1阶以上的每个乘积阶,使用该乘积阶作为参数执行该步骤,例如第2阶或第3阶。步骤310采集和分析输入频率对的互调(IM)和谐波分量。步骤340使用步骤310的结果寻找该校正网络中的滤波器幅度和相位响应。步骤360使用在步骤340中找到的幅度和相位响应,根据所需的幅度和相位响应使用非线性相位滤波器设计算法来设计每个滤波器。步骤380通过设定该滤波器抽头来编程该线性校正器100内的滤波器以对ADC失真进行校正。
As shown in Figure 7, there are four basic steps to calibrating a bank of filters within a filter product in a linearity corrector. For each order of product above order 1, this step is performed using that order of product as a parameter, eg order 2 or order 3. Step 310 acquires and analyzes the intermodulation (IM) and harmonic components of the input frequency pair. Step 340 uses the results of step 310 to find the magnitude and phase response of the filters in the correction network. Step 360 uses the magnitude and phase responses found in step 340 to design each filter according to the desired magnitude and phase response using a nonlinear phase filter design algorithm. Step 380 programs the filter within the
步骤310的基本信号采集和分析可以通过选择如图8中的步骤410所提供的基数据记录长度来完成。在步骤420中选择一组校准频率。步骤430生成两个基于额定校准频率的正弦输入,以及在步骤420中选择的校准指数。步骤440为每个校准中心频率指数计算一组谐波和互调频率。步骤450测试可能引起频率分量重叠的混叠。步骤460或者i)恰在所计算的谐波和互调频率执行一组离散傅里叶变换(DFT),或者ii)执行为完整的一组可能频率生成结果的快速傅里叶变换(FFT),然后,选择在该计算的谐波和互调频率上的输出结果。
The basic signal acquisition and analysis of step 310 can be accomplished by selecting the base data record length as provided in
在步骤410,选择用于DFT分析的基数据记录长度L。为了提高效率,在该校准方法的某些实施例中,将L选择为2的幂。对L的选择对应于基本分析频率F=fs/L,其中fs是采样率。然后将所有频率fm表示为基本分析频率F的谐波(整数倍)m,即fm=mF。角频率被表示为:
In
ωm=2πfm=2πmF=2πmfs/L (方程7) ω m = 2πf m = 2πmF = 2πmf s /L (Equation 7)
在步骤420,选择将用于随后步骤以设计滤波器响应的一组校准频率。这些频率被选择为F的谐波倍数,并且规则间隔在输入频率可以发生的整个尼奎斯特(Nyquist)频带中,但总是排除0(DC)的极限(extreme)和fs/2。
At
在步骤430,对于具有额定校准频率ωc的每个校准指数c,以角频率ωc-1=ωc-ω1和ωc+1=ωc+ω1生成两个正弦输入,其对应于:
At
xc(t)=pc-1sin(ωc-1(t+λc-1))+Qc+1sin(ωc+1(t+λc+1)) (方程8) x c (t) = p c-1 sin(ω c-1 (t+λ c-1 ))+Q c+1 sin(ω c+1 (t+λ c+1 )) (Equation 8)
其中λc是在频率指数c的延迟。在该校准方法的实施例中,幅度{Pc-1,Qc+1}是相似的以改善IM校准结果。任何微小差别可以在之后的校正阶段中去除。在该校准方法的实施例中,选择该校准频率以使得它们使用该ADC输入动态范围的大部分。然后,采集整数倍M组L个相邻的A/D输出样本。每个第M个样本被平均以获得低噪声y(t),t=0...L-1,其中L是上面步骤410中提供的该基数据记录长度。这种类型的简单平均是非常快的,允许对ML的大量值(可以是百万样本或更多)进行快速处理。L应当被选择成使得它不会太小或者使分析频率会分隔的太远。大的L的值可以生成比所需要的更多的校准频率数据,导致后面的算法运行更慢。L=210=1024的值已被成功地使用。
where λ c is the delay at frequency index c. In an embodiment of the calibration method, the magnitudes {P c-1 , Q c+1 } are similar to improve IM calibration results. Any small differences can be removed in a later correction stage. In an embodiment of the calibration method, the calibration frequencies are chosen such that they use a large part of the ADC input dynamic range. Then, an integer multiple of M groups of L adjacent A/D output samples is collected. Every Mth sample is averaged to obtain low noise y(t), t=0...L-1, where L is the base data record length provided in
在步骤440,对于每个校准中心频率指数c(其中0<c<L),产生一组谐波和互调频率。DC项被忽略,因为DC误差会由于许多其他原因而发生。例如,第二阶系统在{ωc-1-ωc+1,2ωc-1,ωc-1+ωc+1,2ωc+1,}具有IM和谐波失真频率,对应的指数:m={2,2c-2,2c,2c+2}。事实上,能够只使用和频(sum-frequency)项m={2c-2,2c,2c+2}来校准。仅使用频率的和项而不使用差项的优点在于,前者不是由任何低阶失真滤波器乘积生成。这包括可以称为第1阶(线性)“失真”系统的原始输入信号。
At
应当注意,在采样的系统中,IM和谐波失真会包含混叠频率分量。因此,在步骤450,执行测试以处理混叠导致频率分量重叠的情况,因为该测量将与该失真模型不一致。对于给定c,生成一组可能的谐波和IM项(DC除外)。在一些实施例中,该组将包含除DC项之外的所有可能的谐波和IM项。对于来自步骤440的列表m中的指数mi的每个频率,由于采样理论不能区分频率间隔为L的混叠分量,所以它们相互卷绕如下:
It should be noted that in sampled systems, IM and harmonic distortion will contain aliased frequency components. Therefore, at
w(mi)=mimodL (方程9) w(m i )=m i mod L (equation 9)
而且,在该卷绕间隔L内,混叠不能在w(mi)和L-w(mi)之间区分。该混叠的指数重新映射(aliased index remapping)是较低范围的解释(interpretation),由下式给出: Also, within this wrapping interval L, aliasing cannot be distinguished between w(m i ) and Lw(m i ). This aliased index remapping is the lower range interpretation, given by:
alias(mi)=min(w(mi),L-w(mi)) (方程10) alias(m i )=min(w(m i ), Lw(m i )) (equation 10)
其中min()是其输入值的最小值。因此0≤alias(m)<L/2。mi到alias(mi)的这种重新映射仅用于对于给定整数mi和L检测任何失真频率冲突。冲突检测大多很容易通过生成所有谐波和IM频率指数来实现,然后如上面在方程9和方程 10中所述重新映射每个频率指数,并且对得到的混叠频率指数值进行数字排序。然后,会发现具有相同重新映射频率指数值的相邻频率指数。如果发现有冲突,在该c值处不进行测量。如果L是2的幂,并且c是偶数,那么{c-1,c+1}总是互素的。从而,冲突仅发生在混叠频率。即使这样,通常冲突也是很少的。例如在第3阶系统中,冲突仅发生在c=L/4时。在这种情况下,互调分量位于2(L/4-1)+(L/4+1)=3L/4-1,所以其混叠频率是在L-(3L/4-1)=L/4+1,该频率也是输入频率。类似地,(L/4-1)+(2L/4+1)=3L/4+1,其混叠到上/4-1,也是输入频率。 where min() is the minimum value of its input value. Therefore 0≤alias(m)<L/2. This remapping of m i to alias(m i ) is only used to detect any distortion frequency collision for a given integer m i and L. Collision detection is mostly easy to implement by generating all harmonic and IM frequency indices, then remapping each frequency index as described above in Equation 9 and Equation 10, and numerically sorting the resulting aliased frequency index values. Then, adjacent frequency indices with the same remapped frequency index value are found. If a conflict is found, no measurement is performed at this value of c. If L is a power of 2, and c is even, then {c-1, c+1} is always relatively prime. Thus, collisions only occur at aliased frequencies. Even then, conflicts are usually rare. For example, in a 3rd order system, collisions only occur when c=L/4. In this case, the intermodulation product is located at 2(L/4-1)+(L/4+1)=3L/4-1, so its aliasing frequency is at L-(3L/4-1)= L/4+1, this frequency is also the input frequency. Similarly, (L/4-1)+(2L/4+1)=3L/4+1, which aliases onto /4-1, is also the input frequency.
在本校准方法的一个实施例中,在所选择的谐波和互调频率处执行一组L-样本的实数输入DFT,如步骤460所示。在每个频率m处的实数和虚数分量使用对于该平均实数样本序列的单个频率DFT来得到:
In one embodiment of the calibration method, a real input DFT of a set of L-samples is performed at the selected harmonic and intermodulation frequencies, as shown in
Xm=Re(Zm) X m = Re(Z m )
Ym=Im(Zm) (方程11) Y m = Im(Z m ) (Equation 11)
其中Re和Im是复输入的实部和虚部。方程11的形式是对于来自结合上述步骤410提供的方程7的正规化采样频率。在可选实施例中,可以使用快速傅里叶变换(FFT)代替多重DFT来获得在每个频率m处的实和虚分量。
where Re and Im are the real and imaginary parts of the complex input. The form of Equation 11 is for the normalized sampling frequency from Equation 7 provided in connection with
在该失真系统中,每个滤波器在这个阶段(stage)具有未知的幅度和相位响应。为了找到这些响应,提供用于该系统的失真的数学模型。基于提供的该模型,可以执行非线性优化。用于第N阶乘积的自调制模型将n个未知滤波器响应表示为每个乘积项的修改输入: In this distorted system, each filter has an unknown magnitude and phase response at this stage. In order to find these responses, a mathematical model of the distortion for the system is provided. Based on this model provided, nonlinear optimization can be performed. The self-modulation model for the Nth order product represents n unknown filter responses as modified inputs for each product term:
(方程12) (Equation 12)
这种自调制模型可以以可选的一般形式重写为: This self-modulation model can be rewritten in an optional general form as:
(方程13) (Equation 13)
其中: in:
(方程14) (Equation 14)
并且 and
Bi,c+1=Ai,c+1/Ai,c-1 (方程15) B i,c+1 = A i,c+1 /A i,c-1 (Equation 15)
假定有足够大的L,如果用于校准的两对频率C-1和C+1足够接近,则对于给定滤波器,在每个频率的延迟可以假定为近似相同,那么方程15可以简化为: Assuming a sufficiently large L, if the two pairs of frequencies C-1 and C+1 used for calibration are close enough, then for a given filter, the delay at each frequency can be assumed to be approximately the same, then Equation 15 can be simplified to :
(方程16) (Equation 16)
对于该第n阶失真系统,变量数等于2n+1。对于使用的每一对校准频率,到ADC的正弦波输入幅度都严密匹配。否则,该系统不能区分在两个不同频率处的它们的幅度之间的差别和每个滤波器的幅度响应中的差别。 For this nth order distortion system, the number of variables is equal to 2n+1. The sine wave input amplitudes to the ADC are closely matched for each pair of calibration frequencies used. Otherwise, the system cannot distinguish the difference between their magnitudes at two different frequencies and the difference in the magnitude response of each filter. the
如果在该两个不同的校准频率处通过每个滤波器的幅度响应是近似相同的,那么更简化的自调制模型可以提供如下: If the magnitude response through each filter is approximately the same at these two different calibration frequencies, then a more simplified self-modulation model can be given as follows:
(方程17) (Equation 17)
通过选择适合这些失真模型中的一个的ADC,如方程13、方程16或方程17所表示的,对于每个滤波通道在每个频率可以找到一组相位和幅度解。表示该失真模型的任何方程都可以被扩展以提供一组互调和谐波频率分量,其对应于上面在步骤440所找到的那些频率分量。该减少可以表示为在每个频率的余弦(实部)和正弦(虚部)项。一旦获得频率项的扩展和收集,连同在步骤460确定的那组DFT一起,那么就可以以符号表示的形式(symbolically)得到在这些表达式的实部和虚部与DFT结果之间的差的平方和,其可以从如上所述的DFT或FFT得到。这导致了对于第2阶失真的大的方程,以及对于每个更高阶的甚至更大的方程。
By choosing an ADC that fits one of these distortion models, as expressed in Equation 13, Equation 16, or Equation 17, a set of phase and magnitude solutions can be found for each filter channel at each frequency. Any equations representing this distortion model can be extended to provide a set of intermodulation and harmonic frequency components corresponding to those found at
因为相位和延迟λ通过角频率ω相关的,即通过: because of phase And the delay λ is related to the angular frequency ω, that is, by:
(方程18) (Equation 18)
代入来自方程7的ωm,并且使用正规化频率(即fs=1),使得模型方程式中的任何方程13、方程16或方程17以频率指数的形式重写。例如,方程16可以重写为: Substituting ω m from Equation 7, and using normalized frequencies (ie, f s =1), rewrites any Equation 13, Equation 16, or Equation 17 in the model equations in frequency exponential form. For example, Equation 16 can be rewritten as:
(方程19) (Equation 19)
例如以阶数n=2分解成实部和虚部,我们扩展方程19并且收集项以获得在四个非DC互调和谐波频率指数的项:{2,2c,2c-2,2c+2}: For example decomposing into real and imaginary parts with order n=2, we extend Equation 19 and collect terms to obtain terms at four non-DC intermodulation and harmonic frequency indices: {2, 2c, 2c-2, 2c+2 }:
(方程20) (Equation 20)
(方程21) (Equation 21)
(方程22) (Equation 22)
(方程23) (Equation 23)
其中该组系数{C,S}被确定为: where the set of coefficients {C, S} is determined as:
对于方程20: For equation 20:
对于方程21: For equation 21:
对于方程22: For equation 22:
对于方程23: For equation 23:
现在,对这些系数和它们相对应的来自方程11的DFT或FFT分量之间的差的平方和进行估计: Now, estimate the sum of squares of the differences between these coefficients and their corresponding DFT or FFT components from Equation 11:
(方程24) (Equation 24)
这里方程24可以表示该目标函数或者误差。对于第2阶的情况,要寻找的未知量可以用向量表示为: Here Equation 24 may represent the objective function or error. For the second-order case, the unknown quantity to be searched can be expressed as a vector:
xc={Kc,B1,c+1,B2,c+1,λ1,c,λ2,c} (方程25) x c ={K c , B 1,c+1 , B 2,c+1 ,λ 1,c ,λ 2,c } (Equation 25)
一旦已经提供了该目标函数,就可以确定每个滤波器的幅度和相位响应。现在参照图9,示出了本校准方法的一个实施例。如步骤540中所示,首先将该目标函数最小化。在最小化该目标函数之后,对幅度执行解后校正(post-solution correction),如步骤560所示。该校正解现在被分解到为每一阶提供的滤波器之间,如步骤580所示。 Once this objective function has been provided, the magnitude and phase response of each filter can be determined. Referring now to FIG. 9, one embodiment of the present calibration method is shown. As shown in step 540, the objective function is first minimized. After minimizing the objective function, a post-solution correction is performed on the magnitude, as shown in step 560 . The corrected solution is now decomposed between the filters provided for each stage, as shown in step 580 . the
为了最小化该目标函数,如步骤540所示,将需要求解非线性方程的系统。可以使用一类基于牛顿(Newton-based)的算法来对每个预期的阶求解这些非线性方程和最小化该目标函数。可能的基于牛顿的算法包括修正牛顿(MN)、高斯一牛顿(GN)和准牛顿(Quasi-Newton)(QN)。在每个搜索迭代k,这些方法都估计该目标函数的数值梯度向量(gk)和该目标函数的Hessian(Sk)的数值逆,或者对于GN和QN方法是该目标函数的Hessian函数的逆的近似。该目标函数的梯度向量和该目标函数的Hessian的逆可以描述如下: To minimize this objective function, as shown in step 540, will require solving a system of nonlinear equations. A class of Newton-based algorithms can be used to solve these nonlinear equations and minimize the objective function for each desired order. Possible Newton-based algorithms include Modified Newton (MN), Gauss-Newton (GN) and Quasi-Newton (QN). At each search iteration k, these methods estimate the numerical gradient vector (g k ) of the objective function and the numerical inverse of the Hessian (S k ) of the objective function, or for the GN and QN methods the Hessian of the objective function inverse approximation. The gradient vector of the objective function and the inverse of the Hessian of the objective function can be described as follows:
在x=xk (方程26) at x = x k (equation 26)
在x=xk (方程27) At x = x k (equation 27)
通过估计该梯度向量和逆Hessian,能够获得可用于最小化该目标函数的搜索方向(dk),其中该搜索方向如下给出: By estimating the gradient vector and the inverse Hessian, the search direction (d k ) that can be used to minimize the objective function can be obtained, where the search direction is given by:
dk=-Skgk (方程28) d k = -S k g k (Equation 28)
该目标函数的梯度向量定义为这样一个向量,其第i个分量是该函数关于其第i个未知变量的偏导数。因此,它是这个阶段的符号结果而非数值。对于对应于方程16的具有5个未知量的第二阶情况,该目标函数由方程24提供: The objective function The gradient vector of is defined as a vector whose ith component is the partial derivative of the function with respect to its ith unknown variable. Therefore, it is a symbolic result of this stage rather than a numerical value. For the second order case with 5 unknowns corresponding to Equation 16, this objective function is given by Equation 24:
Hessian矩阵的第(i,j)个元素是该目标函数对于其第i个和第j个变量的偏导数。再次,对于第2阶情况,该Hessian矩阵如下给出: The (i, j)th element of the Hessian matrix is the partial derivative of the objective function with respect to its i-th and j-th variables. Again, for the 2nd order case, the Hessian matrix is given as:
因此该矩阵元素是该未知变量x的项。该偏导运算符是可交换的,所以Hessian矩阵总是平方对称的(square-symmetric)。 The matrix elements are therefore entries for the unknown variable x. The partial derivative operator is commutative, so the Hessian matrix is always square-symmetric. the
对于该目标函数可以找到相应的梯度和Hessian矩阵。虽然求解这种复杂表达式的导数是非常繁复的,但是可以通过使用符号数学软件工具例如在Mathematica中的符号导数函数来执行计算机化符号计算。可选地,可以使用众所周知的近似来数值地求解任何函数f(x)的导数f′(x): The corresponding gradient and Hessian matrix can be found for this objective function. Although solving the derivatives of such complex expressions is very tedious, computerized symbolic computations can be performed by using symbolic mathematics software tools such as the symbolic derivative function in Mathematica. Alternatively, the derivative f′(x) of any function f(x) can be solved numerically using well-known approximations:
(方程29) (Equation 29)
对于适当小的值Δ,假定该计算精度可用。可以使用符号或者数值微分。符号微分可以通过符号数学软件来提供,通过这种软件提供的这种处理对处理器204使用通用处理器。应当注意,如果已经得到了符号微分,在本校准方法的一些实施例中,可以使用较低级语言例如C语言将这些符号结果编码为函数,以便改善在处理器204中的这种操作的性能。在可选实施例中,可以由处理器使用数值微分代替提供该符号解的编码实施。
For suitably small values of Δ, this computational precision is assumed to be available. Symbolic or numerical differentiation can be used. Symbolic differentiation may be provided by symbolic mathematics software, and such processing provided by such software uses a general-purpose processor for
如上所述,可以通过使用基于牛顿的算法直接或叠代求解逆Hessian。例如,在本校准方法的一个实施例中,使用准牛顿算法叠代确定该Hessian矩阵的逆的近似值。有多个QN叠代的子范畴可以使用。例如可以使用BFGS(Broyden,Fletcher,Goldfarb,Shanno)叠代公式。在本校准方法的一个实施例中,该BFGS叠代公式与弗莱彻线搜索(Fletcher’s Line Search)算法一起使用。 该逆Hessian Sk+1的第(k+1)次BFGS叠代如下给出: As mentioned above, the inverse Hessian can be solved directly or iteratively by using Newton-based algorithms. For example, in one embodiment of the present calibration method, an approximation of the inverse of the Hessian matrix is determined iteratively using a quasi-Newton algorithm. There are multiple subcategories of QN iterations that can be used. For example, the BFGS (Broyden, Fletcher, Goldfarb, Shanno) iteration formula can be used. In one embodiment of the calibration method, the BFGS iterative formula is used with the Fletcher's Line Search algorithm. The (k+1)th BFGS iteration of the inverse Hessian S k+1 is given by:
(方程30) (Equation 30)
其中列向量pk、标量qk和方矩阵rk如下给出: where the column vector p k , the scalar q k and the square matrix r k are given by:
pk=Skγk p k =S k γ k
(方程31) (Equation 31)
Sk(方矩阵)是该逆Hessian的第k次近似值,而S0=I为单位矩阵。应当注意,上标T是转置,例如:是δk的转置。并且列向量: S k (square matrix) is the kth approximation of the inverse Hessian, and S 0 =I is the identity matrix. It should be noted that the superscript T is transpose, eg: is the transpose of δ k . and a column vector:
γk=gk+1-gk (方程32) γ k =g k+1 -g k (Equation 32)
其中gk是较早从(方程26)中获得的梯度向量。对于下一个叠代的该新的解向量估计xk+1由应用到该前一个xk的校正列向量δk给出: where g k is the gradient vector obtained earlier from (Equation 26). The new solution vector estimate xk +1 for the next iteration is given by the correction column vector δk applied to the previous xk :
xk+1=xk+δk (方程33) x k+1 = x k +δ k (Equation 33)
为了寻找每个叠代的未知的δk,使用沿着搜索方向dk的约束搜索。一旦使用方程33找到xk并且使用方程28和方程30找到dk,然后,就找到了非负标量αk,其最小化: To find the unknown δk for each iteration, a constrained search along the search direction dk is used. Once x k is found using Equation 33 and d k is found using Equations 28 and 30, then, a non-negative scalar α k is found that minimizes:
e2(xk+1)=e2(xk+δk)=e2(xk+αkdk) (方程34) e 2 (x k+1 )=e 2 (x k +δ k )=e 2 (x k +α k d k ) (Equation 34)
这是αk中的一维优化问题,而不论该原始问题的维数如何。因而,对这种特定类型方程的求解已知为线搜索。 This is a one-dimensional optimization problem in α k regardless of the dimensionality of the original problem. Thus, the solution of this particular type of equation is known as a line search.
当前的解可估计向量xk,且其相应的搜索方向dk被给定作为弗莱彻线搜索算法的输入,以给出标量值αk。于是,对于方程33中的对xk的列向量校正如下给出: The current solution may estimate a vector x k , and its corresponding search direction d k is given as input to the Fletcher line search algorithm to give a scalar value α k . Then, the column vector correction for x k in Equation 33 is given by:
δk=xk+1-xk=αkdk (方程35) δ k =x k+1 -x k =α k d k (Equation 35)
众所周知,在一般情况下,寻找目标函数的全局最小值是一个困难问题。所找到的最小值总是依赖于该目标函数,但是也可以依赖于该初始条件x0°如果该失真模型能够相当好地符合,那么通常收敛会迅速和可靠。然而,如果该真实的失真机制包括多个失真乘积或者其他一些不遵循该失真模型的机制,则该解会发散。在这种情况下,向一个解前进,并且该误差函数方程24在每次叠代中减少,但是向量x中的未知量之一按指数规律向无穷发散。对BFGS叠代数量的限制可以可靠地检测这种问题。然而,到达这种限制的过程也减慢了该校准算法。 It is well known that finding the global minimum of the objective function is a difficult problem in general. The minimum found always depends on the objective function, but can also depend on the initial condition x 0 ° If the distortion model fits reasonably well, the convergence is usually fast and reliable. However, if the true distortion mechanism includes multiple distortion products or some other mechanism that does not follow the distortion model, the solution will diverge. In this case, a solution is advanced, and the error function equation 24 decreases in each iteration, but one of the unknowns in the vector x diverges exponentially towards infinity. A limit on the number of BFGS iterations can reliably detect this kind of problem. However, reaching this limit also slows down the calibration algorithm.
如果在噪声减少平均后,看到发散,那么可以设置发散失败标记以指示对 于进一步诊断的需要,或者该ADC的失败。 If, after noise reduction averaging, divergence is seen, a divergence failure flag can be set to indicate the need for further diagnostics, or failure of the ADC. the
然而,一旦逼进最小解,则算法收敛是二次的,所以能迅速收敛到可重复的结果。这种特性可以用于探索方程16的模型的解空间。如果一个解收敛到在先找到的解,则可以作为重复解而拒绝。该过程会继续,直到已经获得不能再找到最小值的统计上符合要求的判断。 However, once the minimum solution is approached, the algorithm converges quadratically, so it converges quickly to repeatable results. This property can be used to explore the solution space of the model of Equation 16. A solution can be rejected as a duplicate if it converges to a previously found solution. This process continues until a statistically satisfactory decision has been obtained that no further minimum can be found. the
在本校准方法的一些实施例中,在具有π的邻近整数倍的角度处可能有其他邻近解。这些重复解由于微不足道地相关或“无兴趣”而被辨别并被排除。 In some embodiments of the present calibration method, there may be other adjacent solutions at angles having adjacent integer multiples of π. These duplicate solutions were identified and rejected as trivially relevant or "uninteresting". the
找到解的一个方法是在方程19中以B的随机值开始x,使用: One way to find the solution is to start x with a random value of B in Equation 19, using:
B=eu(Random-1/2) (方程36) B = e u(Random-1/2) (Equation 36)
Random是从0到1的随机实数值。u=0.1的值对于实数ADC数据可以有很好的效果。每个角可以在以下范围中随机产生: Random is a random real value from 0 to 1. A value of u=0.1 can have good results for real ADC data. each corner Can be randomly generated in the following ranges:
(方程37) (Equation 37)
然后可以使用方程18在已知频率将角转变为方程19中的延迟。 The angle can then be converted to a delay in Equation 19 at a known frequency using Equation 18. the
在另一实施例中,通过将用作校准指数c的函数的随机角的初始范围限制到在先前校准中的起作用的范围来寻找已知ADC设计的解。对初始范围的这种限制会加速该解的搜索。 In another embodiment, a solution for a known ADC design is found by restricting the initial range of random angles used as a function of the calibration index c to the range that worked in previous calibrations. This restriction on the initial range speeds up the search for the solution. the
即使该开始值至少被方程37约束,该最终值也可以存在于这些范围之外而进入最接近的相邻重复解中。这是因为该开始点可以存在于在该重复最小值之间的重复的“峰”的另一侧。然而,由于在该间隔π的重复的函数“形状(landscapes)”的相似性,即使更远也不会找到重复解。在本校准方法的一个实施例中,找到了最近的相邻解并且排除了重复解。 Even if the starting value is constrained by at least Equation 37, the final value may exist outside these ranges into the closest adjacent iterative solution. This is because the start point may exist on the other side of the repeated "peak" between the repeated minima. However, due to the similarity of the repeated function "landscapes" at the interval π, no repeated solution will be found even further. In one embodiment of the present calibration method, nearest neighbor solutions are found and duplicate solutions are excluded. the
对于每个校准频率,一旦找到第一解angle,就可以很容易地找到中心解(即角最接近0)。在本校准方法的一个实施例中,所找到的角直接被验证为中心解(在±π/2内)。在可选实施例中,使用multiple=floor(angle/π+0.5)来寻找距该中心解区域最接近的π的整数倍,然后将该π的倍数从该第一解角(solutionangle)中减去以使该角进入该中心区域中。在一些应用中,接近±π/2的解可以随着在另外具有校准频率的角度平滑变化中的在+π/2或-π/2之间的噪声波动。这些波动可以通过在之后的处理中查找角的连续性而得到校正。然后,该BFGS算法的第二次运行可以通过使用被替换的第一解作为好的开始点而迅速找到更准确的中心解。 For each calibration frequency, once the first solution angle is found, the central solution (i.e. the angle closest to 0) can be easily found. In one embodiment of the present calibration method, the found angles are directly verified as central solutions (within ±π/2). In an alternative embodiment, multiple=floor(angle/π+0.5) is used to find the closest integer multiple of π to the central solution region, and then the multiple of π is subtracted from the first solution angle (solution angle) Go to bring the corner into the center area. In some applications, a solution close to ±π/2 may fluctuate with noise between +π/2 or -π/2 in an otherwise smooth change in angle with a calibration frequency. These fluctuations can be corrected by looking for angular continuity in later processing. Then, a second run of the BFGS algorithm can quickly find a more accurate central solution by using the substituted first solution as a good starting point.
从该中心解,可以系统地找到距离该中心解最近的相邻解。如上面寻找该中心解的过程,可以通过将{-π,0,π}的所有组合加到每个角并且使用作为结果的向量作为BFGS解搜索的开始点来找到该重复解。再次,因为每个开始点非常接近该正确值,BFGS算法非常迅速地收敛。对于第2阶搜索有32-1=8个相邻解,对于第3阶搜索有33-1=26个相邻解。 From this central solution, the nearest neighboring solutions to this central solution can be found systematically. As in the process of finding the central solution above, the repeated solution can be found by adding all combinations of {-π, 0, π} to each corner and using the resulting vector as the starting point for the BFGS solution search. Again, because each starting point is very close to the correct value, the BFGS algorithm converges very quickly. There are 3 2 −1=8 adjacent solutions for the 2nd order search and 3 3 −1=26 adjacent solutions for the 3rd order search.
找到这些解之后,可以使用在其他随机开始位置的搜索来寻找任何更多的解,如果它们存在的话。如果一个解与先前找到的解中的一个匹配,则拒绝它。如前面所述,通过由具有符号梯度的BFGS算法找到的解的高重复性而使得验证重复(duplicate)的过程变得更简单。 After finding these solutions, a search at other random starting positions can be used to find any more solutions, if they exist. If a solution matches one of the previously found solutions, it is rejected. As mentioned earlier, the process of verifying duplicates is made easier by the high repeatability of the solutions found by the BFGS algorithm with signed gradients. the
如果一个新解与迄今所找到的任何一个都不匹配,则可以找到其中心解,并且使用与前述相同的方法找到其所有相邻解。在本校准方法的一个实施例中,富有成效的搜索结果重设超时计数器(tmeout counter),而寻找新解的失败则减少该超时计数器。如果该超时(timeout)到达零,则停止对其他解的搜索。选择根据方程24给出最好的误差测量的中心解作为对于该校准频率指数的最终解。 If a new solution does not match any found so far, its central solution can be found, and all its neighbors can be found using the same method as before. In one embodiment of the calibration method, fruitful search results reset a timeout counter (tmeout counter), while failures to find new solutions decrement the timeout counter. If this timeout reaches zero, the search for other solutions stops. The central solution that gives the best error measure according to Equation 24 is chosen as the final solution for the calibrated frequency index. the
在本校准方法的一个实施例中,如果已经在先前的校准频率指数cprev找到一个解,则可以使用它作为在c的下一次搜索的开始点。如果它不能收敛,则使用前述的慢的随机搜索方法。 In one embodiment of the present calibration method, if a solution has been found at the previous calibration frequency index c prev , it can be used as the starting point for the next search at c. If it fails to converge, the aforementioned slow random search method is used.
如果对于特定的c没有找到解,可以使用在cnext的解作为开始点进行第二次扫描(pass)。如果仍然没有找到解,那么可以使用相邻值之间的修补(patching)或内插。如果对太多的校准值指数都没有能找到解,则该ADC是有故障的,可以设定一个故障标记。 If no solution is found for a particular c, a second pass can be made using the solution at c next as a starting point. If a solution is still not found, then patching or interpolation between adjacent values can be used. If no solution can be found for too many calibration value indices, then the ADC is faulty and a fault flag can be set.
如果对于所有校准频率已经找到可以接受的一组懈,则进入该自调制系统的乘积的每个通道的幅度和相位响应的特征在于该组选定的离散的校准频率。利用这些频率的均匀分布,对于每个通道的响应可以由如图2-4中的FIR滤波器所表示。在本校准方法的一个实施例中,现在对每个滤波器的系数进行叠代寻找。 If an acceptable set of calibration frequencies has been found for all calibration frequencies, then the magnitude and phase response of each channel into the product of the self-modulation system is characterized by the set of selected discrete calibration frequencies. With a uniform distribution of these frequencies, the response for each channel can be represented by an FIR filter as in Figures 2-4. In one embodiment of the calibration method, the coefficients of each filter are now iteratively found. the
在本校准方法的另一实施例中,对来自方程25的该组向量xc在将它们传送到该滤波器设计之前进行校正,如步骤560所示。在本校准方法的实施例中,该校准输入的幅度在合理的校准范围上将不会显著影响该滤波器响应。从方程14可以看出,这种依赖性通过用除Kc而可以被消除,其中n是该乘积阶指数。而且,在一些实施例中,在方程8的两个校准正弦输入的幅度中的任何差 别还应当对该滤波器响应具有可以忽略的影响。在这种情况下,不仅该失真滤波器的相对响应,而且该校准正弦输入的相对幅度都会影响该测量结果。因此,在这些实施例中,使用相对幅度Pc-1和Qc+1来进行校正。该比率: In another embodiment of the calibration method, the set of vectors xc from Equation 25 are calibrated before they are passed to the filter design, as shown in step 560 . In an embodiment of the calibration method, the magnitude of the calibration input will not significantly affect the filter response over a reasonable calibration range. As can be seen from Equation 14, this dependence is achieved by using can be eliminated by dividing Kc , where n is the order index of the product. Also, in some embodiments, any difference in the amplitudes of the two calibration sinusoidal inputs of Equation 8 should also have negligible effect on the filter response. In this case, not only the relative response of the distortion filter, but also the relative magnitude of the calibration sinusoidal input affects the measurement. Therefore, in these embodiments, the relative magnitudes P c-1 and Q c+1 are used for correction. The ratio:
Rc=Qc+1/Pc-1 (方程38) R c =Q c+1 /P c-1 (Equation 38)
给出了在x中B参数被高估的量。因此对方程25中的x的该参数针对第n阶校准进行校正以给出新向量Xc如: gives the amount by which the B parameter is overestimated in x. This parameter of x in equation 25 is therefore corrected for the nth order calibration to give a new vector X as :
(方程39) (Equation 39)
在任何校准频率,滤波器乘积系统的组合幅度响应是每个滤波器的幅度响应的函数。因此,我们可以使得一个滤波器的系数变大两倍,而另一个缩小两倍,而具有相同的结果。系统幅度响应的变化在校准频率之间可以是重要的。我们可以通过使得乘积中的每个滤波器对于第n阶失真校正系统具有相同的来自方程39中第一项的第1/n次方根响应,从而在滤波器乘积系统中的所有滤波器中平均分散跟踪幅度响应变化的负荷,以使: At any calibration frequency, the combined magnitude response of the filter product system is a function of the magnitude response of each filter. Thus, we can make the coefficients of one filter twice as large and the other twice smaller, with the same result. Variations in the magnitude response of the system can be significant between calibration frequencies. We can achieve this across all filters in the filter product system by making each filter in the product have the same 1/nth root response from the first term in Equation 39 for the nth order distortion corrected system The average dispersion tracks the magnitude response to varying loads such that:
(方程40) (equation 40)
对于第n阶失真系统,在频率指数c的每个向量Xc中有n对幅度和频率响应。对n个滤波器中的一个任意指定一对幅度和相位响应,对作为频率的函数的每个滤波器可能会产生非平滑幅度响应、相位响应,或者两者。非平滑响应可以产生不能对选择的滤波器长度很好地跟踪预期响应的滤波器设计。因而,该幅度响应和相位响应被分配到每一阶可用的滤波器之间,如步骤580所示。因为一组足够密集的校准频率通常会导致对于相邻校准指数的延迟响应之间的高的相关度,所以在本校准方法的一个实施例中,通过以该校准循环周期(1/fc-1)的一半为模,测试相对于在频率指数cprev处的前一组的新组可能的置换,来获得在该新组延迟和先前一组延迟之间的更好的配合。在奇数个滑移(slips)的情况下,将对应于半个循环的延迟应用到该滤波器之一。在本校准方法的实施例中,例如采用方程16所述的模型的实施例,每个相位值具有相应的幅度,所以重新排列相位也重新排列相应的幅度。如果两个相位交叉,它们可以被分组为对一个滤波器的最小相位值和对另一滤波器的最大相位值。在每个相位图上导致的绞缠(kink)不会像不连续性一样对所得到的滤波器质量不利,而是产生可行的滤波器设计,如果提供足够的滤波器抽头的话。 For an nth order distorted system, there are n pairs of amplitude and frequency responses in each vector Xc of frequency index c. Arbitrarily specifying a pair of magnitude and phase responses to one of the n filters may produce a non-smooth magnitude response, phase response, or both for each filter as a function of frequency. A non-smooth response can result in a filter design that does not track the expected response well for the chosen filter length. Thus, the magnitude and phase responses are distributed among the available filters at each stage, as shown in step 580 . Because a sufficiently dense set of calibration frequencies usually results in a high degree of correlation between the delayed responses to adjacent calibration indices, in one embodiment of the calibration method, by using the calibration cycle period (1/f c- Modulo half of 1 ), test possible permutations of the new set relative to the previous set at frequency index c prev to obtain a better fit between this new set of delays and the previous set of delays. In case of an odd number of slips, a delay corresponding to half a cycle is applied to one of the filters. In embodiments of the calibration method, such as those employing the model described in Equation 16, each phase value has a corresponding magnitude, so rearranging the phases also rearranges the corresponding magnitudes. If two phases cross, they can be grouped into the minimum phase value for one filter and the maximum phase value for the other filter. The resulting kink on each phase map is not as detrimental to the resulting filter quality as a discontinuity, but results in a feasible filter design, provided enough filter taps are provided.
通过前面的校准步骤,对于每个滤波器路径都获得一组适当分组的幅度和 相位响应。图6中的滤波器设计步骤360使用在步骤340计算的该幅度和相位响应设计每个滤波器,以给出对该计算的响应的近似。在射频(RF)应用的情况,使用该ADC的上Nyquist频带的中间部分,而不对该频带中的外部频率区域进行校准。这意味着该外部频率是不受约束的。如图10所示,在本校准方法的实施例中,使用叠代过程来完成该滤波器设计和寻找该滤波器抽头。在可选实施例中,可以使用简单的逆FFT。 Through the previous calibration steps, an appropriately grouped set of magnitude and phase responses is obtained for each filter path. The filter design step 360 in FIG. 6 designs each filter using the magnitude and phase responses calculated in step 340 to give an approximation of the calculated response. In the case of radio frequency (RF) applications, the middle part of the upper Nyquist band of the ADC is used without calibration for the outer frequency regions in the band. This means that the external frequency is not constrained. As shown in Figure 10, in an embodiment of the calibration method, an iterative process is used to accomplish the filter design and find the filter taps. In an alternative embodiment, a simple inverse FFT can be used. the
如步骤610所示,对每个通道选择一个滤波器长度。在本校准方法的一个实施例中,对于所有通道使用相同的滤波器长度。在可选实施例中,对于部分或所有通道使用不同的滤波器长度。在本可选实施例中,可以需要额外的延迟以补偿该不同的滤波器长度。该滤波器长度可以至少部分依赖于该预期的性能和被校准的ADC。以示例的方式,使用了全部63抽头的滤波器长度或者全部127抽头的滤波器长度。 As shown in step 610, a filter length is selected for each channel. In one embodiment of the calibration method, the same filter length is used for all channels. In alternative embodiments, different filter lengths are used for some or all channels. In this alternative embodiment, an additional delay may be required to compensate for this different filter length. The filter length can depend at least in part on the expected performance and the ADC being calibrated. By way of example, a full filter length of 63 taps or a full filter length of 127 taps are used. the
在步骤620,选择FFT长度并且将该幅度和相位响应转换为复直角坐标的滤波器频率响应向量。该FFT长度应当比在步骤610选择的滤波器长度要长。例如,在本校准方法的实施例中,选择512个样本的实数FFT长度。因为该FFT比滤波器长度长,所以这里将对应于滤波器抽头的频率之外的值初始化为零。 At step 620, an FFT length is selected and the magnitude and phase responses are converted to a filter frequency response vector in complex Cartesian coordinates. The FFT length should be longer than the filter length selected in step 610 . For example, in an embodiment of the present calibration method, a real FFT length of 512 samples is chosen. Because the FFT is longer than the filter length, values other than frequencies corresponding to filter taps are initialized to zero here. the
在步骤630,执行该滤波器频率响应向量的逆FFT以获得一组实数滤波器抽头,但是还有扩展到该FFT长度例如512的抽头。在时域中,超出该选择的滤波器长度的抽头被强制为零。 At step 630, an inverse FFT of the filter frequency response vector is performed to obtain a set of real filter taps, but also taps extended to the FFT length, eg 512. In the time domain, taps beyond this chosen filter length are forced to zero. the
在步骤640,执行前向FFT以回到频域。该频率响应向量的一些区域应当是不受约束的。在所关心的频率的FFT槽(bins)被重写回对于该预期幅度和频率响应的原始值,使得该不受约束的频率槽(frequency bins)不变。 At step 640, a forward FFT is performed to go back to the frequency domain. Some regions of the frequency response vector should be unconstrained. The FFT bins at the frequency of interest are rewritten back to the original values for the expected magnitude and frequency response, leaving the unconstrained frequency bins unchanged. the
重复步骤630和640以叠代收敛到预期解。一旦在步骤630提供的该滤波器抽头已经从先前的叠代中变得稳定,就找到了该滤波器抽头。 Steps 630 and 640 are repeated to iteratively converge to the desired solution. Once the filter tap provided at step 630 has become stable from the previous iteration, the filter tap is found. the
一旦从步骤630获得该滤波器抽头,就可以如图3中的步骤380所提供的那样对硬件编程。该编程滤波器乘积系统现在能够对ADC谐波和互调失真进行校正。 Once the filter taps are obtained from step 630, the hardware can be programmed as provided at step 380 in FIG. The programmed filter product system is now capable of correcting for ADC harmonic and intermodulation distortion. the
本领域普通技术人员将会清楚,可以对本发明的上述实施例细节进行许多改变,而不脱离其基本原则。因此,本发明的范围应当由所附的权利要求来确定。 It will be apparent to those of ordinary skill in the art that many changes may be made to the details of the above-described embodiments of the present invention without departing from the basic principles thereof. Accordingly, the scope of the invention should be determined by the appended claims.
Slavin.txt Slavin.txt
Mathematica code for ADC Correction Algorithm. Mathematica code for ADC Correction Algorithm.
(*Copyright 2005 Tektronix Inc.*) (*Copyright 2005 Tektronix Inc.*)
(*by Keith Slavin*) (*by Keith Slavin*)
(*COPYRIGHT NOTIFICATION (*COPYRIGHT NOTIFICATION
*Pursuant to 37 C.F.R.1.71(e),applicant notes that a portion of this disclosure *Pursuant to 37 C.F.R.1.71(e), applicant notes that a portion of this disclosure
contains material that contains material that
*is subject to and for which is claimed copyright protection,such as,but not *is subject to and for which is claimed copyright protection, such as, but not
limited to,source code listings, limited to, source code listings,
*screen shots,user interfaces,or user instructions,or any other aspects of this *screen shots, user interfaces, or user instructions, or any other aspects of this
submission for which copyright submission for which copyright
*protection is or may be available in any jurisdiction.The copyright owner has no *protection is or may be available in any jurisdiction. The copyright owner has no
objection to the facsimile objection to the facsimile
*reproduction by anyone of the patent document or patent disclosure,as it appears *reproduction by anyone of the patent document or patent disclosure, as it appears
in the Patent and Trademark office in the Patent and Trademark office
*patent file or records.All other rights are reserved,and all other *patent file or records. All other rights are reserved, and all other
reproduction,distribution, reproduction, distribution,
*creation of derivative works based on the contents,public display,and public *creation of derivative works based on the contents, public display, and public
performance of the application performance of the application
*or any part thereof are prohibited by applicable copyright law. *or any part thereof are prohibited by applicable copyright law.
*) *)
BeginPackage[″correction`″,″Global`″] BeginPackage["correction`", "Global`"]
(*frequency Indexing:i1=i-1,i2=i+1*) (*frequency Indexing: i1=i-1, i2=i+1*)
(* (*
*design filters to correct ADC output.lowF,hiF are normalized *design filters to correct ADC output.lowF,hiF are normalized
*frequencies from 0 to 0.5(of fs).′data′is a 2-Darray of acquired *frequencies from 0 to 0.5(of fs).'data'is a 2-Darray of acquired
*ADC data in/login/keith/adc_orrection/xcal_data6/summary.To load, *ADC data in/login/keith/adc_correction/xcal_data6/summary.To load,
*type:<<Z:adc_correction\xcal_data6\summary;The result is in″data″. *type:<<Z:adc_correction\xcal_data6\summary; The result is in "data".
*Type:ProcessData[data,0.1,0.4,127,10^-12]to get the filter *Type: ProcessData[data, 0.1, 0.4, 127, 10^-12] to get the filter
*coefficients in the form: *coefficients in the form:
*{{2nd_orde_f1_list,2nd_order_f2_list}, *{{2nd_orde_f1_list, 2nd_order_f2_list},
*{3rd_order_f1_list,3rd_orde_f2_list,3rd_order_f3_list}} *{3rd_order_f1_list, 3rd_orde_f2_list, 3rd_order_f3_list}}
*) *)
ProcessData[caldata_,calFreqLo_,calFreqHi_,correctFilterLen_,error_]:= ProcessData[caldata_, calFreqLo_, calFreqHi_, correctFilterLen_, error_]: =
Module[ Module[
{order,responses2,correctionFilters2,responses3,correctionFilters3, {order, responses2, correctionFilters2, responses3, correctionFilters3,
correctionFilters}, correctionFilters},
order=2; order=2;
Print[″Generate′rsponses2′:″]; Print[″Generate′rsponses2′:″];
responses2=ProcessCalData[ca]data,order,calFreqLo,calFreqHi,error]; responses2=ProcessCalData[ca]data, order, calFreqLo, calFreqHi, error];
(*design the correction filters from the cal responses*) (*design the correction filters from the cal responses*)
print[″Generate′correctionFilters2':″]; print["Generate'correctionFilters2':"];
correctionFilters2=DesignFilters[responses2,correctFilterLen]; correctionFilters2 = DesignFilters[responses2, correctFilterLen];
order=3; order=3;
Print[″Generate′responses3′:″]; Print[″Generate′responses3′:″];
responses3=ProcessCalData[caldata,order,calFreqLo,calFreqHi,error]; responses3 = ProcessCalData[caldata, order, calFreqLo, calFreqHi, error];
Print[″Generate′correctionFilters3′:″]; Print[″Generate′correctionFilters3′:″];
correctionFilters3=DesignFilters[responses3,correctFilterLen]; correctionFilters3 = DesignFilters[responses3, correctFilterLen];
Return[{correctionFilters2,correctionFilters3}]; Return[{correctionFilters2, correctionFilters3}];
] ]
Page1 Page1
Slavin.txt Slavin.txt
(* (*
* Run a calibration on randomly generated distortion filters,and then correct * Run a calibration on randomly generated distortion filters, and then correct
* the same distortion on a multi-sine input signal. * the same distortion on a multi-sine input signal.
* (*Note:0.2...0.3 range puts 3rd order IM in 0.1...0.4fs * (*Note: 0.2...0.3 range puts 3rd order IM in 0.1...0.4fs
* and 2nd order IM from 0...0.1 and from 0.4...0.5fs.*) * and 2nd order IM from 0...0.1 and from 0.4...0.5fs.*)
* testFreqLo=0.2; * testFreqLo = 0.2;
* testFreqHi=0.3; * testFreqHi=0.3;
* testFreqStep=0.004; (*step in fs units from testFreqLo to testFreqHi*) * testFreqStep=0.004; (*step in fs units from testFreqLo to testFreqHi*)
* calFreqLo=0.1;(*low calibration range in fs units*) * calFreqLo=0.1; (*low calibration range in fs units*)
* calFreqHi=0.4; (*high calibration rage in fs units*) * calFreqHi=0.4; (*high calibration rage in fs units*)
* distortFilterLen=63;(*odd length of all distorting filters*) * distortFilterLen=63; (*odd length of all distorting filters*)
* spread=4.0;(*spread(samples)of random distorting filters*) * spread=4.0; (*spread(samples) of random distorting filters*)
* analysisLen=1024;(*samples in DFT analysis of cal frequencies*) * analysisLen=1024; (*samples in DFT analysis of cal frequencies*)
* freqPairs=128;(*frequency pairs in cal(must divide analysisLen)*) * freqPairs=128; (*frequency pairs in cal(must divide analysisLen)*)
* correctFilterLen=63;(*correction filter lengths(must be odd)*) * correctFilterLen=63; (*correction filter lengths(must be odd)*)
* testLen=32768;(*samples used in test signal analysis*) * testLen=32768; (*samples used in test signal analysis*)
* *
* these three parameters are in LSB units.They make * these three parameters are in LSB units.They make
* noise+distortion+original tones with similar amplitudes to the * noise+distortion+original tones with similar amplitudes to the
* AD6645 ADC: * AD6645 ADC:
* *
* distortionAmpl=0.04; * distortionAmpl = 0.04;
* tonePairAmpl=15000.0; * tonePairAmpl = 15000.0;
* noiseAmpl=2.0; * noiseAmpl = 2.0;
*) *)
Demo[]:= Demo[]:=
Module[ Module[
{} {}
MainTest[0.2,0.3,0.004,0.1,0.4,63,4.0,1024,128,63,32768, MainTest[0.2, 0.3, 0.004, 0.1, 0.4, 63, 4.0, 1024, 128, 63, 32768,
0.04,15000.0,0.01]; 0.04, 15000.0, 0.01];
] ]
MainTest[testFreqLo_,testFreqHi_,testFreqStep_,calFreqLo_,calFreqHi_, MainTest[testFreqLo_, testFreqHi_, testFreqStep_, calFreqLo_, calFreqHi_,
distortFilterLen_,spread_,analysisLen_,freqPairs_, distortionFilterLen_, spread_, analysisLen_, freqPairs_,
correctFilterLen_,testLen_, correctFilterLen_, testLen_,
distortionAmpl_,tonePairAmpl_,noiseAmpl_]:= DistortionAmpl_, tonePairAmpl_, noiseAmpl_]:=
Module[ Module[
{margin,testdata,order, {margin, testdata, order,
filter2,filter3,filters, filter2, filter3, filters,
caldata,error, caldata, error,
responses2,responses3, responses2, responses3,
correctionFilters2,correctionFilters3,correctionFilters, correctionFilters2, correctionFilters3, correctionFilters,
distorted,corrected}, distorted, corrected},
Print[″Version0.3″]; Print[″Version0.3″];
(*generate second-order random distortion filters*) (*generate second-order random distortion filters*)
print[″Generate'filter2':″]; print["Generate'filter2':"];
order=2: order=2:
filter2=GenFilters[distortFilterLen,order,spread]; filter2 = GenFilters[distortFilterLen, order, spread];
(*generate third-order random distortion filters*) (*generate third-order random distortion filters*)
Print[″Generate'filter3':″]; Print["Generate'filter3':"];
order=3; order=3;
filter3=GenFilters[distortFilterLen,order,spread]; filter3 = GenFilters[distortFilterLen, order, spread];
(*combine filter data*) (*combine filter data*)
filters={filter2,filter3}; filters = {filter2, filter3};
(*generate multi-tone test data record*) (*generate multi-tone test data record*)
Page2 Page2
slavin.txt slavin.txt
Print[″Generate′testdata′:″]; Print[″Generate′testdata′:″];
margin=(distortFilterLen-1)+(correctFilterLen-1); margin=(distortFilterLen-1)+(correctFilterLen-1);
testdata=GenTest[testLen,mrgin, testdata=GenTest[testLen, mrgin,
testFreqLo,testFreqHi,testFreqStep]; ... testFreqLo, testFreqHi, testFreqStep];
(*generate a set of cal data tone pairs*) (*generate a set of cal data tone pairs*)
print[″Generate'caldata':″]; print["Generate'caldata':"];
cal data=DistortCal[filters,analysisLen,freqPairs, cal data = DistortCal[filters, analysisLen, freqPairs,
distortionAmpl,tonePairAmpl,noiseAmpl]; distortionAmpl, tonePairAmpl, noiseAmpl];
(*process the cal data to get filter responses*) (*process the cal data to get filter responses*)
error=10^-12; error=10^-12;
correctionFilters= correctionFilters=
ProcessData[caldata,calFreqLo,calFreqHi,correctFilterLen,error]; ProcessData[caldata, calFreqLo, calFreqHi, correctFilterLen, error];
(*distort the test data using the original filters*) (*distort the test data using the original filters*)
print[″Generate′distorted':″]; print["Generate'distorted':"];
distorted=DistortData[testdata,filters, distorted=DistortData[testdata, filters,
distortionAmpl,tonePairAmpl,noiseAmpl]; distortionAmpl, tonePairAmpl, noiseAmpl];
(*plot the distorted signal*) (*plot the distorted signal*)
PlotunwindowedFFT[Take[distorted,testLen]]; PlotunwindowedFFT[Take[distorted, testLen]];
Print[″Generate′corrected':″]; Print["Generate'corrected':"];
corrected=CorrectData[distorted,correctionFilters]; corrected = CorrectData[distorted, correctionFilters];
(*plot the corrected signal*) (*plot the corrected signal*)
PlotUnwindowedFFT[Take[corrected,testLen]]; PlotUnwindowedFFT[Take[corrected, testLen]];
] ]
(*aliases data set by first finding data mod n,and then (*aliases data set by first finding data mod n, and then
wrapping data>n/2 to n-data*) wrapping data>n/2 to n-data*)
AliasF[data_,n_]:= AliasF[data_, n_]:=
Module[ Module[
{len,modData,i}, {len, modData, i},
len=Length[data]; len=Length[data];
modData=Mod[data,n]; modData = Mod[data,n];
Return[Table[Min[modData[[i]],n-modData[[i]],{i,1,len}]]; Return[Table[Min[modData[[i]], n-modData[[i]], {i, 1, len}]];
] ]
(*Expand distortion product*) (*Expand distortion product*)
AllTerms[i_,order_]:= AllTerms[i_, order_] :=
Module[ Module[
{t,tt,j,q0,q1,q2,q3,q3a,q4,q5,q6,q7,q8,terms,len}, {t, tt, j, q0, q1, q2, q3, q3a, q4, q5, q6, q7, q8, terms, len},
If[order=0, If[order=0,
Return[{0}]; Return[{0}];
]; ];
q0=TrigReduce[(Cos[(i-1)tt]+Cos[(i+1)tt])^order]; q0=TrigReduce[(Cos[(i-1)tt]+Cos[(i+1)tt])^order];
(*extract tt variable outside as a common factor for each cos term*) (*extract tt variable outside as a common factor for each cos term*)
q1=q0/.Cos[a_]:>Cos[Apart[a]]; q1=q0/.Cos[a_]:>Cos[Apart[a]];
(*expand into seperate terms*) (*expand into separate terms*)
q2=Expand[q1]; q2 = Expand[q1];
q3=Table[q2[[j]],{j,1,Length[q2]}]; q3 = Table[q2[[j]], {j, 1, Length[q2]}];
(*find the cosine terms only,discard their coefficients,and convert (*find the cosine terms only, discard their coefficients, and convert
any DC term to 0*) any DC term to 0*)
q4=Table[If[NumericQ[q3[[j]]],0,q3[[j]]/(q3[[j]]/.tt->0)], q4=Table[If[NumericQ[q3[[j]]], 0, q3[[j]]/(q3[[j]]/.tt->0)],
{j,1,Length[q3]}]; {j, 1, Length[q3]}];
(*eliminate the Cos[]arount each term*) (*eliminate the Cos[]around each term*)
q6=q4/.Cos[a_]:>Apart[a]; q6=q4/.Cos[a_]:>Apart[a];
(*form(k*i+m)*tt->k*i+m for integer k,m*) (*form(k*i+m)*tt->k*i+m for integer k, m*)
q7=q6/.a_*tt:>a; q7=q6/.a_*tt:>a;
Page3 Page3
Slavin.txt Slavin.txt
q8=q7; q8=q7;
(*make i term positive:if k is -ve,then its derivative is -ve*) (*make i term positive:if k is -ve,then its derivative is -ve*)
terms=Table[If[D[q8[[j]],i]<0,-q8[[j]],q8[[j]]],{j,1,Length[q8]}]; terms=Table[If[D[q8[[j]], i]<0, -q8[[j]], q8[[j]]], {j, 1, Length[q8]}];
Return[Expand[terms]]; Return[Expand[terms]];
] ]
(* (*
* * * * *
*S is an approximation to the inverse of the Hessian,G. *S is an approximation to the inverse of the Hessian, G.
* *
*BFGS iteration is: *BFGS iteration is:
* T T T T * T T T T
* ga S ga dx dx dx ga S+S ga dx * ga S ga dx dx dx ga S+S ga dx
* S[k+1]=S+(1+--------)------ -(------------------) * S[k+1]=S+(1+-------)------ -(------------------)
* T T T * T T T T
* dx ga dx ga dx ga * dx ga dx ga dx ga
* T T T T T * T T T T T T T T
* (dx ga+ga S ga)dx dx dx ga S+S ga dx * (dx ga+ga S ga)dx dx dx ga S+S ga dx
* =S+----------------------- -(------------------) * =S+----------------------- -(------------------)
* T 2 T * T T 2 T T
* *
(dx ga) dx ga dx ga
* *
* T T T * T T T
* If:v1=s ga,v2=dx ga,v3=v1 dx =S ga dx * If: v1=s ga, v2=dx ga, v3=v1 dx =S ga dx
* then: * then:
* T T T * T T T
* (v2+ga v1)dx dx (v3+v3) * (v2+ga v1)dx dx (v3+v3)
* S[k+1]=S+----------------- - -------- * S[k+1]=S+----------------- - --------
* 2 * 2
* (v2) v2 * (v2) v2
* *
*Note:SetPrecision[]is used to compensate for the gradual loss in *Note: SetPrecision[] is used to compensate for the gradual loss in
*accuracy that Mathematica imposes on iterative calculations. *accuracy that Mathematica imposes on iterative calculations.
*) *)
BFGS[x0_,vars_,gradients_,objectiveFunc_,epsi_,maxIterations_]:= BFGS[x0_,vars_,gradients_,objectiveFunc_,epsi_,maxIterations_]:=
Module[ Module[
{len,k,x,S,g,err,ds,a,ax,dx,xnew,g1,ga,v1,v2,v3,part0,part1,part2, {len, k, x, S, g, err, ds, a, ax, dx, xnew, g1, ga, v1, v2, v3, part0, part1, part2,
eTable,rTable,dxdxT,max,subst,residual}, eTable, rTable, dxdxT, max, subst, residual},
len=Length[x0]; len=Length[x0];
k=0; k=0;
(*convert 1-D list to a 2-D column vector*) (*convert 1-D list to a 2-D column vector*)
x=Transpose[SetPrecision[{x0},39]]; x = Transpose[SetPrecision[{x0}, 39]];
(*S[k]is an approximation to the inverse of the modified Hessian of (*S[k] is an approximation to the inverse of the modified Hessian of
e2[x]at x=x[k]*) e2[x]at x=x[k]*)
S=IdentityMatrix[len];(*S is a square matrix and always symmetric*) S=IdentityMatrix[len]; (*S is a square matrix and always symmetric*)
g=GradFunc[x,vars,gradients];(*returns a gradient column vector*) g = GradFunc[x, vars, gradients]; (*returns a gradient column vector*)
err=Norm[g];(*returns sqrt of sum of squares of elements of g*) err=Norm[g]; (*returns sqrt of sum of squares of elements of g*)
eTable=Table[0,{maxIterations}]; eTable = Table[0, {maxIterations}];
rTable=Table[-40.0,{maxIterations}]; rTable = Table[-40.0, {maxIterations}];
While[(err>epsi)&&(k<maxIterations), While[(err>epsi)&&(k<maxIterations),
ds=-S.g;(*ds is a direction column vector*) ds=-S.g; (*ds is a direction column vector*)
(*scalar′a′line search result*) (*scalar'a'line search result*)
ax=FletcherLineSearch[x,ds,vars,gradients,objectiveFunc]; ax = FletcherLineSearch[x, ds, vars, gradients, objectiveFunc];
a=SetPrecision[ax,39]; a = SetPrecision[ax,39];
dx=a*ds;(*dx is a column vector*) dx=a*ds; (*dx is a column vector*)
xnew=x+dx;(*new column vector result*) xnew=x+dx; (*new column vector result*)
g1=GradFunc[xnew,vars,gradients];(*column vector result*) g1 = GradFunc[xnew, vars, gradients]; (*column vector result*)
ga=g1-g;(*also a column vector*) ga = g1-g; (*also a column vector*)
(*dx.Transpose[dx] is a square symmetric matrix*) (*dx.Transpose[dx] is a square symmetric matrix*)
dxdxT=dx.Transpose[dx]; dxdxT = dx.Transpose[dx];
v1=s.ga;(*also a column vector*) v1=s.ga; (*also a column vector*)
Page 4 Page 4
Slavin.txt Slavin.txt
v2[=(Ttanspose[ga].dx)[[1]][[1]];(*v2 is scalar*) v2[=(Ttanspose[ga].dx)[[1]][[1]]; (*v2 is scalar*)
If[v2==0.0, If[v2==0.0,
Print[″BFGS error:v2=″,v2]; Print[″BFGS error:v2=″, v2];
Print[″Iteration:″,k]; Print[″Iteration:″,k];
Print[″v2=″,v2]; Print[″v2=″, v2];
Print[″g=″,g]; Print[″g=″,g];
Print[″S=″,S]; Print[″S=″,S];
Print[″Determinant[S]=″,Det[S]]; Print[″Determinant[S]=″, Det[S]];
Print[″Inverse[S]=″,Inverse[S]]; Print[″Inverse[S]=″, Inverse[S]];
Print[″ds=″,ds]; Print[″ds=″,ds];
Print[″a=″,a]; Print[″a=″, a];
Print[″dx=″,dx]; Print[″dx=″,dx];
Print[″xnew=″,xnew]; Print[″xnew=″,xnew];
Print[″g1=″,g1]; Print[″g1=″,g1];
Print[″ga=″,ga]; Print[″ga=″,ga];
Abort[]; Abort[];
]; ];
v3=v1.Transpose[dx];(*v3 is a square matrix*) v3=v1.Transpose[dx]; (*v3 is a square matrix*)
(*Transpose[ga].v1 is a scalar,so part0 is scalar*) (*Transpose[ga].v1 is a scalar, so part0 is scalar*)
part0=(v2+(Transpose[ga].v1)[[1]][[1]])/(v2^2); Part0=(v2+(Transpose[ga].v1)[[1]][[1]])/(v2^2);
part1=par0*dxdxT;(*part1 is square symmetric*) part1=par0*dxdxT; (*part1 is square symmetric*)
(*any matrix added to its transpose is always square symmetric*) (*any matrix added to its transpose is always square symmetric*)
part2=(v3+Transpose[v3])/v2;(*part2 is square symmetric*) Part2=(v3+Transpose[v3])/v2; (*part2 is square symmetric*)
(*S(old and new)is square symmetric*) (*S(old and new)is square symmetric*)
S=SetPrecision[S+part1-part2,39]; S = SetPrecision[S+part1-part2, 39];
x=SetPrecision[xnew,39]; x = SetPrecision[xnew, 39];
g=SetPrecision[g1,39]; g = SetPrecision[g1, 39];
subst=-Table[vars[[j]]->x[[j]][[1]],{j,1,len}]; Subst=-Table[vars[[j]]->x[[j]][[1]],{j,1,len}];
residual=Log[objectiveFunc/.subst]; residual = Log[objectiveFunc/.subst];
err=Norm[dx]; err = Norm[dx];
(*Print[″iteration=″,k,″,dx=″,err];*) (*Print[″iteration=″,k,″,dx=″,err];*)
(*Print[″x=″,Flatten[x]];*) (*Print[″x=″, Flatten[x]];*)
k+=1; k+=1;
eTable[[k]]=err; eTable[[k]]=err;
rTable[[k]]=residual; rTable[[k]]=residual;
If[residual<-40.0, If[residual<-40.0,
Break[]; Break[];
]; ];
]; ];
If[k==maxIterations, If [k==maxIterations,
(*Print[″BFGS Failed to converge.Final vector:″,x];*) (*Print[″BFGS Failed to converge.Final vector:″,x];*)
Return[]; Return[];
]; ];
(* Print[″Total iterations=″,k,″,Line error=″,err];*) (*Print[″Total iterations=″, k,″, Line error=″, err];*)
(* Print[″Finished:x=″,Flatten[x]];*) (*Print[″Finished:x=″, Flatten[x]];*)
Return[Flatten[x]]; Return[Flatten[x]];
] ]
(**) (**)
CorrectData[data_,filters_]:= CorrectData[data_, filters_]:=
Module[ Module[
{maxOrder,len,c,sum,j,nrSamples,samples,t}, {maxOrder, len, c, sum, j, nrSamples, samples, t},
maxOrder=Length[filters]; maxOrder = Length[filters];
len=Length[filters[[1,1]]]; len=Length[filters[[1,1]]];
c=(len-1)/2; c = (len-1)/2;
sum=0; sum=0;
For[j=1,j<=maxorder,++j, For[j=1, j<=maxorder, ++j,
sum+=GenDistortion[data,filters[[j]]]; sum + = GenDistortion[data, filters[[j]]];
]; ];
Page5 Page5
Slavin.txt Slavin.txt
nrSamples=Length[sum]; nrSamples = Length[sum];
Print[″nrSamples=″,nrSamples]; Print[″nrSamples=″, nrSamples];
samples=Take[data,{c+1,nrSamples+c}]-sum; samples = Take[data, {c+1, nrSamples+c}]-sum;
Return[samples]; Return[samples];
] ]
(*make real tap filter have the required DC'delay′(in sample units, (*make real tap filter have the required DC'delay'(in sample units,
where 0 is the first tap or sample.Usually DCdelay=Length[tans]/2 where 0 is the first tap or sample.Usually DCdelay=Length[tans]/2
is used*) is used*)
DCadjust[realtaps_,DCdelay_]:= DCadjust[realtaps_, DCdelay_]:=
Module[ Module[
{newtaps,taps,i,sum1,sum2,offset,div}, {newtaps, taps, i, sum1, sum2, offset, div},
taps=Length[realtaps]; taps = Length[realtaps];
sum1=Sum[irealtaps[[i+1]],{i,1,taps-1}]; sum1 = Sum[irealtaps[[i+1]], {i, 1, taps-1}];
sum2=Sum[realtaps[[i+1]],{i,0,taps-1}]; sum2 = Sum[realtaps[[i+1]], {i, 0, taps-1}];
div=taps*(DCdelay-(taps-1)/2); div = taps * (DCdelay-(taps-1)/2);
If[div==0.0, If[div==0.0,
Print[″DCadjust divide by zero.″]; Print[″DCadjust divide by zero.″];
Abort[]; Abort[];
]; ];
offset=(sum1-sum2*DCdelay)/div; offset=(sum1-sum2*DCdelay)/div;
Print[″offset=″,offset]; Print[″offset=″, offset];
newtap=realtaps+offset; newtap=realtaps+offset;
Return[newtaps]; Return[newtaps];
] ]
(*find the′delay'of a filter at DC*) (*find the'delay'of a filter at DC*)
DCdelay[realtaps_]:= DCdelay[realtaps_]:=
Module[ Module[
{sumc,sumci,i,taps}, {sumc, sumci, i, taps},
(*calculate the dc delay without Arg[]aliasing.*) (*calculate the dc delay without Arg[]aliasing.*)
taps=Length[realtaps]; taps = Length[realtaps];
sumc=Sum[realtaps[[i+1]],{i,0,taps-1}]; sumc = Sum[realtaps[[i+1]], {i, 0, taps-1}];
If[sumc==0.0, If[sumc==0.0,
Print[″DCdelay divide by zero.″]; Print[″DCdelay divide by zero.″];
Abort[]; Abort[];
]; ];
sumci=Sum[realtaps[[i+1]]i,{i,1,taps-1}]; sumci=Sum[realtaps[[i+1]]i, {i, 1, taps-1}];
Return[N[sumci/sumc]]; Return[N[sumci/sumc]];
] ]
Delays[list_,n_]:= Delays[list_,n_]:=
Module[ Module[
{i,L,len,reals,angle,diff,offset,items,complex, {i, L, len, reals, angle, diff, offset, items, complex,
delay,radiansPerSample,prevAngle,newDelay}, delay, radiansPerSample, prevAngle, newDelay},
L=Length[list]; L = Length[list];
len=n/2; len=n/2;
items=len+1; Items=len+1;
reals=Join[list,Table[0,{i,1,n-L}]]; Reals=Join[list, Table[0, {i, 1, n-L}]];
complex=Take[Fourier[reals,{FourierParameters->{-1,1}}],items]; complex = Take[Fourier[reals, {FourierParameters->{-1, 1}}], items];
delays=Table[0,{items}]; delays = Table[0, {items}];
delays[[1]]=DCdelay[list]; Delays[[1]]=DCdelay[list];
For[i=1,i<items,++i, For[i=1, i<items, ++i,
If[Abs[complex[[i+1]]]<10^-12, If[Abs[complex[[i+1]]]<10^-12,
delays[[i+1]]=delays[[i]], Delays[[i+1]]=delays[[i]],
(*else*) (*else*)
radiansPerSample=N[Pi*i/len]; ` radiansPerSample=N[Pi*i/len];
delay=delays[[i]]; delay = delays[[i]];
prevAngle=delay*radiansPerSample; prevAngle = delay * radiansPerSample;
angle=Mod[Arg[complex[[i+1]]],pi,prevAngle-Pi/2]; angle = Mod[Arg[complex[[i+1]]], pi, prevAngle-Pi/2];
Page6 Page6
Slavin.txt Slavin.txt
newDelay=angle/radiansPerSample; newDelay=angle/radiansPerSample;
delays[[i+1]]=newDelay; Delays[[i+1]]=newDelay;
]; ];
]; ];
(* possible oversampling to interpolate*) (* possible oversampling to interpolate*)
For[i=1,i<len,++i, For[i=1, i<len, ++i,
If[Abs[complex[[i+1]]]<10^-12, If[Abs[complex[[i+1]]]<10^-12,
delays[[i+1]]=(delays[[i]]′+delays[[i+2]])/2; Delays[[i+1]]=(delays[[i]]′+delays[[i+2]])/2;
]; ];
]; ];
Return[delays-(L-1)/2]; Return[delays-(L-1)/2];
] ]
(* (*
* design filters to correct ADC output. * design filters to correct ADC output.
* DesignFilters[] works on the output of ProcessCalData * DesignFilters[] works on the output of ProcessCalData
*) *)
DesignFilters[data_,correctionFilterLen_]:= DesignFilters[data_, correctionFilterLen_]:=
Module[ Module[
{fi,samples,freqs,start,end,skip,i,j,freqIndex,ampl,temp,cycle, {fi, samples, freqs, start, end, skip, i, j, freqIndex, ampl, temp, cycle,
refDlyA,refDlyB,dly,qq,K,logsize,logFreqs,mags,parts,filters, refDlyA, refDlyB, dly, qq, K, logsize, logFreqs, mags, parts, filters,
nrVars,gainA,gainB,delays,totalGains,xx,sortList,sorted nrVars, gainA, gainB, delays, totalGains, xx, sortList, sorted
prev,next,permute,undef,modified,odd}, prev, next, permute, undef, modified, odd},
xx=data; xx=data;
freqs=Length[xx]-1;(*input is oflength 2^m+1*) freqs=Length[xx]-1; (*input is oflength 2^m+1*)
logFreqs=Log[2,freqs]; logFreqs = Log[2, freqs];
If[!IntegerQ[logfreqs], If [! IntegerQ[logfreqs],
Print[Length[xx]-1 is not a power of 2.″]; Print[Length[xx]-1 is not a power of 2.″];
Abort[]; Abort[];
]; ];
logSize=logFreqs+3; logSize=logFreqs+3;
samples=2^logSize; samples = 2^logSize;
skip=samples/(2*freqs); skip=samples/(2*freqs);
Print[″skip=″,skip]; Print[″skip=″, skip];
Print[″***************** correction phase ******************″]; Print[″******************************************″];
undef=-2; undef=-2;
start=end=undef; start=end=undef;
For[fi=0,fi<=freqs,++fi, For[fi=0, fi<=freqs, ++fi,
i=fi+1; i=fi+1;
If[Length[xx[[i]]]==0, If[Length[xx[[i]]]==0,
If[(start!=undef)&&(end==undef), If[(start!=undef)&&(end==undef),
end=fi-1; end=fi-1;
]; ];
,(*else*) , (*else*)
If[start==undef, If[start==undef,
start=fi; start=fi;
]; ];
]; ];
]; ];
order=0;(*default is set later*) Order=0; (*default is set later*)
Print[″start=″,start,″,end=″,end]; Print[″start=″, start, ″, end=″, end];
For[fi=start,fi<=end,++fi, For[fi=start, fi<=end, ++fi,
i=fi+1; i=fi+1;
freqIndex=fi*skip; freqIndex = fi*skip;
cycle=N[samples/freqIndex]; `` cycle=N[samples/freqIndex];
If[fi==start, If[fi==start,
nrVars=Length[xx[[i]]]; nrVars = Length[xx[[i]]];
order=(nrVars-1)/2; Order=(nrVars-1)/2;
page7 page7
Slavin.txt Slavin.txt
odd=False; odd=False;
,(*else*) , (*else*)
(*a previous result exists*) (*a previous result exists*)
prev=Table[xx[[i-1,order+1+j]],{j,1,order}]; Prev=Table[xx[[i-1, order+1+j]], {j, 1, order}];
next=Tabl[xx[[i,order+1+j]],{j,1,order}; next = Tabl[xx[[i, order+1+j]], {j, 1, order};
{permute,modified,odd}=MatchMod[prev,next,cycle]; {permute, modified, odd} = MatchMod[prev, next, cycle];
xx[[i]]=Flatten[{xx[[i,1]], xx[[i]]=Flatten[{xx[[i,1]],
Table[xx[[i,1+permute[[j]]]],{j,1,order}], Table[xx[[[i,1+permute[[j]]]],{j,1,order}],
modified}]; modified}];
]; ];
If[xx[[i,1]]<0.0 If[xx[[i,1]]<0.0
xx[[i,1]]=-xx[[i,1]]; xx[[i,1]]=-xx[[i,1]];
odd=!odd; odd=! odd;
]; ];
If[odd, If[odd,
If[xx[[i,order+2]]>0.0, If[xx[[i, order+2]]>0.0,
xx[[i,order+2]]-=cycle*0.5, xx[[i, order+2]]-=cycle*0.5,
xx[[i,order+2]]+=cycle*0.5 xx[[i, order+2]]+=cycle*0.5
]; ];
]; ];
(* Print[″end:xx[[″,i,″]]=″,xx[[i]]];*) (*Print[″end:xx[[″,i,″]]=″,xx[[i]]];*)
]; ];
(*initialize uncalibrated regions to allow later matrix transpose*) (*initialize uncalibrated regions to allow later matrix transpose*)
For[fi=0,fi<start,++fi, For[fi=0, fi<start, ++fi,
i=fi+1; i=fi+1;
xx[[i]]=Table[0,{2*order+1}]; xx[[i]]=Table[0,{2*order+1}];
]; ];
For[fi=end+1,fi<=freqs,++fi, For[fi=end+1, fi<=freqs, ++fi,
i=fi+1; i=fi+1;
xx[[i]]=Table[0,{2*order+1}]; xx[[i]]=Table[0,{2*order+1}];
]; ];
qq=Transpose[xx]; qq = Transpose[xx];
K=qq[[1]]; K=qq[[1]];
Print[″K:″]; Print[″K:″];
PlotFreq[K,start,end]; PlotFreq[K, start, end];
For[j=1,j<=order.++j, For[j=1, j<=order.++j,
Print[″Amplitude″,j]; Print["Amplitude", j];
PlotFreq[qq[[1+j]],start,end]; PlotFreq[qq[[1+j]], start, end];
]; ];
For[j=1,j<=order,++j, For[j=1, j<=order, ++j,
Print[″Delay″,j]; Print[″Delay″,j];
PlotFreq[qq[[order+1+j]],start,end]; PlotFreq[qq[[order+1+j]], start, end];
]; ];
(*gainA^(order-1)*gainB=K,gainA applies to allfilters except one (*gainA^(order-1)*gainB=K, gainA applies to allfilters except one
which uses gainB*) which uses gainB*)
totalGains=Take[K,{start+1,end+1}]; totalGains = Take[K, {start+1, end+1}];
gainA=Abs[totalGains]^(1/order); gainA=Abs[totalGains]^(1/order);
gainB=totalGains/(gainA^(order-1)); gainB=totalGains/(gainA^(order-1));
delays=Table[Take[qq[[j+order+1]],{start+1,end+1}],{j,1,order}]; delays=Table[Take[qq[[j+order+1]], {start+1, end+1}], {j, 1, order}];
filters=Table[Fj]terDesign[If[j==order,gainB,gainA],delays[[j] filters=Table[Fj]terDesign[If[j==order, gainB, gainA], delays[[j]
freqs,start,correctionFilterLen],{j,1,order}]; freqs, start, correctionFilterLen], {j, 1, order }];
For[j=1,j<=order,++j, For[j=1, j<=order, ++j,
ListPlot[filters[[j]],{Plotjoined->True,PlotRange->All}]; ListPlot[filters[[j]], {Plotjoined->True, PlotRange->All}];
]; ];
mags=Table[Magnitude[filters[[i]],samples],{i,1,order}]; mags = Table[Magnitude[filters[[i]], samples], {i, 1, order}];
parts=Table[Take[mags[[j]],{1,1+freqs*skip,skip}],{j,1,order}]; parts=Table[Take[mags[[j]],{1,1+freqs*skip,skip}],{j,1,order}];
Print[″Original Combined amplitude response:″]; Print[″Original Combined amplitude response:″];
PlotFreq[K,start,end]; PlotFreq[K, start, end];
Print[econstructed combned response:″]; Print[econstructed combined response:″];
Page8 Page8
Slavin.txt Slavin.txt
ampl=Product[parts[[i]],{j,1,order}]; ampl = Product[parts[[i]],{j,1,order}];
PlotFreq[amp],start,end]; PlotFreq[amp], start, end];
Print[″Amplitude response difference:″]; Print[″Amplitude response difference:″];
PlotFre[K-amp],start,end]; PlotFre[K-amp],start,end];
refDlys=Table[GenDelay[fi]ters[[j]],2*freqs],{j,1,order}]; refDlys=Table[GenDelay[fi]ters[[j]],2*freqs],{j,1,order}];
For[j=1,j<=order,++j, For[j=1, j<=order, ++j,
Print[″Reconstructed delay response″,j,″:″]; Print[″Reconstructed delay response″,j,″:″];
PlotRawDelay[refDlys[[j]]]; PlotRawDelay[refDlys[[j]]];
]; ];
Return[filters]; Return[filters];
] ]
(*single frequency DFT with gain normalization,returns a complex value*) (*single frequency DFT with gain normalization, returns a complex value*)
DFT[data_,m_]:= DFT[data_,m_]:=
Module[ Module[
{len,sum,t}, {len, sum, t},
len=Length[data]; len=Length[data];
sum=0; sum=0;
For[t=0,t<len,++t, For[t=0, t<len, ++t,
sum+=(Exp[I*2*pi*m*t/len] data[[t+1]]);(*1-based array indexing*) sum+=(Exp[I*2*pi*m*t/len] data[[t+1]]); (*1-based array indexing*)
]; ];
Return[2sum/len]; Return[2sum/len];
] ]
(* (*
*Generates a broad-spectrum set of distorted calibration data. *Generates a broad-spectrum set of distorted calibration data.
*′filters′={filter2,filter3,...} *'filters' = {filter2, filter3, ...}
*where filter2={{<taps>},{<taps>} *where filter2={{<taps>}, {<taps>}
*wherefilter3={{<taps>},{<taps>},{<taps>}} *wherefilter3={{<taps>},{<taps>},{<taps>}}
*and each list<taps>has the same length′len′(must be odd). *and each list<taps>has the same length′len′(must be odd).
*For example,before runnning Distortcal[],with *For example, before running Distortcal[], with
*′distortFilterLen=63;′and′spread=4.0;′ *'distortFilterLen=63;'and'spread=4.0;'
*filter2=GenFilters[distortFilterLen,2,spread]; *filter2=GenFilters[distortFilterLen, 2, spread];
*filter3=GenFilters[distortFilterLen,3,spread]; *filter3=GenFilters[distortFilterLen, 3, spread];
*filters={filter2,filter3}; *filters={filter2, filter3};
*′sx′is the output data record length for each test frequency pair. *′sx′is the output data record length for each test frequency pair.
*′freqs′is one more than the number of output data frequency *'freqs'is one more than the number of output data frequency
*sets,e.g.for 127 sets,freqs=128. *sets, e.g.for 127 sets, freqs=128.
*Note sx/freqs must be integer. *Note sx/freqs must be integer.
*′distortion is the distortion level in output lsb units *′distortion is the distortion level in output lsb units
*′signal′is the two-tone amplitude in output lsb units. *‘signal’is the two-tone amplitude in output lsb units.
*′noise′is the added noise standard deviation in output lsb units. *′noise′is the added noise standard deviation in output lsb units.
*Values that match the records acquired for the AD6645 are; *Values that match the records acquired for the AD6645 are;
*DataGen[filters,1024,128,0.04,15000.0,2.0]; *DataGen[filters, 1024, 128, 0.04, 15000.0, 2.0];
*) *)
DistortCal[fiters_,sx_,freqs_,distortion_,signal_,nois_]:= DistortCal[fiters_, sx_, freqs_, distortion_, signal_, noise_]:=
Module[ Module[
{error,order,q,span,data,i,j,len,qfreq,f1,f2,phase1,phase2, {error, order, q, span, data, i, j, len, qfreq, f1, f2, phase1, phase2,
sines,samples,t,c,sum,maxOrder}, sines, samples, t, c, sum, maxOrder},
maxOrder=Lenqth[filters]; maxOrder = Lenqth[filters];
len=Length[filters[[1,1]]]; len=Length[filters[[1,1]]];
error=False; error=False;
If[!IntegerQ[sx], If [! IntegerQ[sx],
Print[″Analysis length is not integer.″]; Print["Analysis length is not integer."];
error=True; error=True;
]; ];
If[!IntegerQ[freqs], If [! IntegerQ[freqs],
Print[″Frequency range is not integer.″]; Print[″Frequency range is not integer.″];
error=True; error=True;
Page9 Page9
Slavin.txt Slavin.txt
]; ];
If[!IntegerQ[len], If [! IntegerQ[len],
Print[″Filter lengths are not integer."]; Print[″Filter lengths are not integer.”];
error=True; error=True;
]; ];
If[Mod[sx,4]!=0, If[Mod[sx,4]! = 0,
print[″Analysis length is not a multiple of 4.″]; print[″Analysis length is not a multiple of 4.″];
error=True; error=True;
]; ];
If[Mod[sx,freqs]!=0, If[Mod[sx, freqs]! = 0,
Print[″Analysis length is not a multiple of the number of″ Print[″Analysis length is not a multiple of the number of″
″frequencies.n″]; "frequencies.n"];
error=True; error=True;
]; ];
If[!OddQ[len], If [! OddQ[len],
Print[″Filter lengths are not odd.″]; Print["Filter lengths are not odd."];
error=True; error=True;
]; ];
If[error, If[error,
Abort[]; Abort[];
]; ];
c=(len+1)/2; c=(len+1)/2;
q=2.0*Pi/sx; q=2.0*Pi/sx;
span=sx/(2*freqs); span=sx/(2*freqs);
data=Table[0,{freqs-1}]; data = Table[0,{freqs-1}];
For[i=1,i<freqs,++i, For[i=1, i<freqs, ++i,
qfreq=span*i; qfreq=span*i;
f1=qfreq-1; f1=qfreq-1;
f2=qfreq+1; f2=qfreq+1;
phase1=Random[Rea],{0,2*pi},10]; phase1 = Random[Rea], {0, 2*pi}, 10];
phase2=Random[Rea],{0,2*pi},10]; Phase2 = Random[Rea], {0, 2*pi}, 10];
(*Length[sines]=sx+len-1*) (*Length[sines]=sx+len-1*)
sines=Table[(Cos[q*f1*t-phase1]+Cos[q*f2*t-phase2]), Sines=Table[(Cos[q*f1*t-phase1]+Cos[q*f2*t-phase2]),
{t,0,sx+len-2}]; {t,0,sx+len-2}];
(*Length[samples]=Length[sines]+1-len=sx*) (*Length[samples]=Length[sines]+1-len=sx*)
sum=0; sum=0;
For[j=1,j<=maxOrder,++j, For[j=1, j<=maxOrder, ++j,
sum+=GenDistortion[sines,filters[[j]]]; sum + = GenDistortion[sines, filters[[j]]];
]; ];
samples=distortion*sum; samples=distortion*sum;
samples+=Table[Gaussian[0,noise],{t,1,sx}]; samples+=Table[Gaussian[0, noise], {t, 1, sx}];
samples+=signal*Take[sines,{c,sx+c-1}] samples+=signal*Take[sines, {c, sx+c-1}]
(*output highest frequencies first*) (*output highest frequencies first*)
data[[Freqs-i]]=samples; data[[Freqs-i]]=samples;
]; ];
Return[data]; Return[data];
] ]
(**) (**)
DistortData[data_,filters_,distortion_,signal_,noise_]:= DistortData[data_, filters_, distortion_, signal_, noise_]: =
Module[ Module[
{maxOrder,len,c,sum,j,nrSamples,samples,t}, {maxOrder, len, c, sum, j, nrSamples, samples, t},
maxOrder=Length[filters]; maxOrder = Length[filters];
len=Length[filters[[1,1]]]; len=Length[filters[[1,1]]];
c=(len-1)/2; c = (len-1)/2;
sum=0; sum=0;
For[j=1,j<=maxOrder,++j, For[j=1, j<=maxOrder, ++j,
sum+=GenDistortion[data,filters[[j]]]; sum + = GenDistortion[data, filters[[j]]];
]; ];
nrSamples=Length[sum]; nrSamples = Length[sum];
Page10 Page10
Slavin.txt Slavin.txt
Print[″nrSamples=″,nrSamples]; Print[″nrSamples=″, nrSamples];
samples=distortion*sum; samples=distortion*sum;
If[noise!=0, If [noise! = 0,
samples+=Table[Gaussian[0,noise],{t,1,nrSamples}]; samples+=Table[Gaussian[0, noise], {t, 1, nrSamples}];
]; ];
samples+=signal* Take[data,{c+1,nrSamples+c}]; samples+=signal* Take[data, {c+1, nrSamples+c}];
Return[samples]; Return[samples];
] ]
(* (*
*′symbVars′is the list of symbolic variables; *'symbVars'is the list of symbolic variables;
* Flatten[{k,Table[a[j],{j,1,order}],Table[d[j],{j,1,order}}]; * Flatten[{k, Table[a[j], {j, 1, order}], Table[d[j], {j, 1, order}}];
*′ix′is the index symbol to use(passed in at a higher level). *′ix′is the index symbol to use(passed in at a higher level).
*′sx′is the symbolic time scale factor. *′sx′is the symbolic time scale factor.
*′dft′is a symbolic variable that is expanded to a list,used internally *'dft'is a symbolic variable that is expanded to a list, used internally
* and also returned as the list′dfts′. * and also returned as the list′dfts′.
*Returns; *Returns;
*′symbolicBins′:a list of IM and harmonic frequences as a functi on of the *'symbolicBins': a list of IM and harmonic frequencies as a function on of the
* frequency index′ix′. * frequency index'ix'.
* ′e2′: a symbolic error equation as a function of ix,sx,symbVars * ′e2′: a symbolic error equation as a function of ix, sx, symbVars
* and′dfts′. * and'dfts'.
*′g':a list of symboli gradient equations that are derivatives of *′g’: a list of symboli gradient equations that are derivatives of
* ′e2′with respect to each of the′symbVars'variable list. * 'e2'with respect to each of the'symbVars'variable list.
*′dfts′:a list of symbolic variables:{dft[1],dft[2],...} *'dfts': a list of symbolic variables: {dft[1], dft[2],...}
*) *)
DoInit[symbVars_,ix_,sx_,dft_]:= DoInit[symbVars_, ix_, sx_, dft_]:=
Module[ Module[
{e2,g,j,nrAnalysisBins,symbolicBins,nrVars,dfts,dft,p}, {e2, g, j, nrAnalysisBins, symbolicBins, nrVars, dfts, dft, p},
(* (*
*Create the symbolic expressions for the objective function e2 *Create the symbolic expressions for the objective function e2
*and all its partial derivatives with respect to 'vars′. *and all its partial derivatives with respect to 'vars'.
*Note:only really needs to be called once for multiple analysis *Note: only really needs to be called once for multiple analysis
*frequencies,as the results are purely symbolic. *frequencies, as the results are purely symbolic.
*) **)
{symbolicBins,p}=Terms[ix,sx,symbVars]; {symbolicBins, p} = Terms[ix, sx, symbVars];
nrAnalysisBins=Length[symbolicBins]; nrAnalysisBins = Length[symbolicBins];
dfts=Table[dft[j],{j,1,nrAnalysisBins}]; dfts = Table[dft[j], {j, 1, nrAnalysisBins}];
(*e2 is the symbolic sum of the squares of the differences between the (*e2 is the symbolic sum of the squares of the differences between the
predicted vlues′p′and′dfts'at each analysis bin*) predicted vlues'p'and'dfts'at each analysis bin*)
e2=Sum[(p[[j]][[1]]-Re[dfts[[j]]])^2+ e2=Sum[(p[[j]][[1]]-Re[dfts[[j]]])^2+
(p[[j]][[2]]-Im[dfts[[j]]])^2,{j,1,nrAnalysisBins}]; (p[[j]][[2]]-Im[dfts[[j]]])^2,{j,1,nrAnalysisBins}];
(*calculate symbolic partial derivatives*) (*calculate symbolic partial derivatives*)
nrVars=Length[symbVars]; nrVars = Length[symbVars];
g=Table[D[e2,symbVars[[j]]],{j,1,nrvars}]; g = Table[D[e2, symbVars[[j]]], {j, 1, nrvars}];
Return[{symbolicBins,e2,g,dfts}]; Return[{symbolicBins, e2, g, dfts}];
] ]
(* (*
*′e2′is symbolic error equation. *′e2′is symbolic error equation.
*′g′is symbolic gradiente equation. *′g′is symbolic gradiente equation.
*′dfts′is array of symbolic dft results. *′dfts′is array of symbolic dft results.
*′symbVars′is list of veriables that BGGS is attempting to solve. *′symbVars′is list of veriables that BGGS is attempting to solve.
*′y′is list of dft results. *′y′is list of dft results.
*′x′is set of start values for BFGS. *′x′is set of start values for BFGS.
*′sx′is samples symbol ′s′is actual sample value. *′sx′is samples symbol ′s′is actual sample value.
*′ix′is frequency index symbol,′i′is actual index value. *'ix'is frequency index symbol,'i'is actual index value.
*′acc′ is BFGS accuracy goal. *‘acc’ is BFGS accuracy goal.
*′maxIterations′limits BFGS search time. *'maxIterations'limits BFGS search time.
Page11 Page11
Slavin.txt Slavin.txt
*) *)
Dosolve[e2_,g_,dfts_,symbVars_,y0_,x_,sx_,s_,ix_,i_,acc_, Dosolve[e2_, g_, dfts_, symbVars_, y0_, x_, sx_, s_, ix_, i_, acc_,
maxIterations_]:= MaxIterations_]:=
Module[ Module[
{e2n,gn,j,nrAnalysisBins,subst,substx,xnew,subst2,residual,len,y}, {e2n, gn, j, nrAnalysisBins, subst, substx, xnew, subst2, residual, len, y},
y=SetPrecision[y0,39]; y = SetPrecision[y0, 39];
nrAnalysisBins=Length[y]; nrAnalysisBins = Length[y];
(*evaluate the symbolic expressions with the known constants*) (*evaluate the symbolic expressions with the known constants*)
substx=Table[dfts[[j]]->y[[j]],{j,1,nrAnalysisBins}]; substx = Table[dfts[[j]]->y[[j]],{j,1,nrAnalysisBins}];
subst=Flatten[{sx->s,jx->i,substx}]; Subst = Flatten[{sx->s, jx->i, substx}];
e2n=e2/.subst; e2n=e2/.subst;
gn=g/.subst; gn=g/.subst;
xnew=BFGS[x,symbVars,gn,e2n,acc,maxIterations]; xnew=BFGS[x,symbVars,gn,e2n,acc,maxIterations];
len=Length[xnew]; len = Length[xnew];
subst2=Table[symbVars[[j]]->xnew[[j]],{j,1,len}]; Subst2=Table[symbVars[[j]]->xnew[[j]],{j,1,len}];
residul=e2n/.subst2; Residul=e2n/.subst2;
Return[{xnew,residual}]; Return[{xnew, residual}];
] ]
ExpFunc[q_]:=If[q<-100,0,Exp[q]] ExpFunc[q_]:=If[q<-100, 0, Exp[q]]
(*takes sparce gain and delay lists,places them in a′size'length list (*takes sparse gain and delay lists, places them in a'size'length list
at″start′(zero based),for iterative filter calculations*) at "start'(zero based), for iterative filter calculations*)
FilterDesign[gain_,dlyin_,size_,start_,requiredtaps_]:= FilterDesign[gain_, dlyin_, size_, start_, requiredtaps_]:=
Module[ Module[
{l1,l2,ampl,delay,dly,n,taps,nrtaps,offset,i,j, {l1, l2, ampl, delay, dly, n, taps, nrtaps, offset, i, j,
fftsize,deviation,avgdev,min,bestTaps}, fftsize, deviation, avgdev, min, bestTaps},
l1=Length[gain]; l1=Length[gain];
l2=Length[dlyin]; l2=Length[dlyin];
If[l1!=l2, If[l1! = l2,
Print[″Missmatched gain and delay list lengths.″]; Print["Missmatched gain and delay list lengths."];
Abort[]; Abort[];
]; ];
If[EvenQ[requiredtaps], If[EvenQ[requiredtaps],
Print[″Number of taps must be odd.″]; Print[″Number of taps must be odd.″];
Abort[]; Abort[];
]; ];
If[(start<=0)||((start+l1)>=size) If[(start<=0)||((start+l1)>=size)
Print[″start and size values illegal for″,l1,″gains and delays.″]; Print["start and size values illegal for", l1, "gains and delays."];
Abort[]; Abort[];
]; ];
dly=dlyin+size;(*center the delays*) dly=dlyin+size; (*center the delays*)
n=size+1; n=size+1;
ampl=Flatten[{Table[0,{start}],gain,Table[0,{n-start-l1}]}]; ampl = Flatten[{Table[0, {start}], gain, Table[0, {n-start-l1}]}];
delay=Flatten[{Table[size,{start}],dly,Table[size,{n-start-l2}]}]; delay=Flatten[{Table[size,{start}],dly,Table[size,{n-start-l2}]}];
If[Length[ampl]!=n, If[Length[ampl]! = n,
Print[″Internalerror:Length[ampl]=″,Length[ampl],″,n=″,n]; Print[″Internalerror:Length[ampl]=″, Length[ampl],″,n=″,n];
Abort[]; Abort[];
]; ];
If[Length[delay]!=n, If[Length[delay]! = n,
Print[″Internal error:Length[delay]=″,Length[delay],″,n=″,n]; Print[″Internal error:Length[delay]=″, Length[delay],″,n=″,n];
Abort[]; Abort[];
]; ];
fftsize=2*size; fftsize=2*size;
offset=Floor[reqiredtaps/2]; offset=Floor[reqiredtaps/2];
min=Infinity; min=Infinity;
For[j=0,j<100,++j,(*note:Break[] for small j in loop*) For[j=0, j<100, ++j, (*note:Break[] for small j in loop*)
taps=Taps[ampl,delay]; Taps = Taps[ampl, delay];
nrtaps=Length[taps]; nrtaps = Length[taps];
(*set coeffcients outside desired filter size to zero (*set coefficients outside desired filter size to zero
Page12 Page12
Slavin.txt Slavin.txt
For[i=0,i<fftsize,++i, For[i=0, i<fftsize, ++i,
If[(i<(size-offset))||(i>=(size+offset)), If[(i<(size-offset))||(i>=(size+offset)),
taps[[i+1]]=0; Taps[[i+1]]=0;
]; ];
]; ];
{ampl,delay}=Response[taps]; {ampl, delay} = Response[taps];
(* overwrite gain and delay with original values in critical (* overwrite gain and delay with original values in critical
region*) region*)
deviation=0.0; deviation=0.0;
For[i=start,i<start+l1,++i, For[i=start, i<start+l1, ++i,
deviation+=Abs[delay[[i+1]]-dly[[i-start+1]]]; deviation+=Abs[delay[[i+1]]-dly[[i-start+1]]];
]; ];
avgdev=deviation/(l1+1); Avgdev=deviation/(l1+1);
If[avgdev<min, If[avgdev<min,
min=avgdev; min=avgdev;
bestTaps=taps; bestTaps = taps;
]; ];
Print[″Loop″,j,″:average absolute delay deviation=″,avgdev]; Print[″Loop″,j,″:average absolute delay deviation=″,avgdev];
If[j==25, If[j==25,
Break[]; Break[];
]; ];
For[i=start,i<start+l1,++i, For[i=start, i<start+l1, ++i,
ampl[[i+1]]=gain[[i-start+1]]; Ampl[[i+1]]=gain[[i-start+1]];
delay[[i+1]]=dly[[i-start+1]]; Delay[[i+1]]=dly[[i-start+1]];
]; ];
For[i=0,i<start,++i, For[i=0, i<start, ++i,
delay[[i+1]]=delay[[start+1]]; Delay[[i+1]]=delay[[start+1]];
]; ];
]; ];
taps=Table[bestTaps[[i+1]],{i,size-offset,size+offset}]; Taps = Table[bestTaps[[i+1]], {i, size-offset, size+offset}];
dcdelay=DCdelay[taps]; dcdelay = DCdelay[taps];
margin=Floor[0.45 requiredtaps]; margin=Floor[0.45 requiredtaps];
If[dcdelay<margin, If[dcdelay<margin,
Print[″limiting lower,″]; Print[″limiting lower,″];
taps=DCadjust[taps,margin]; Taps = DCadjust[taps, margin];
{ampl,delay}=Response[taps], {ampl, delay} = Response[taps],
(*else*) (*else*)
If[dcdelay>=requiredtaps-margin, If[dcdelay>=requiredtaps-margin,
Print[″limiting upper,″]; Print[″limiting upper,″];
taps=DCadjust[taps,requiredtaps-margin-1]; Taps = DCadjust[taps, required taps-margin-1];
{ampl,delay}=Respons[taps]; {ampl, delay} = Respons[taps];
]; ];
]; ];
Return[taps]; Return[taps];
] ]
(*x and ds are 2-D column vectors,′vars′is a list of variables in the (*x and ds are 2-D column vectors, 'vars' is a list of variables in the
gradients(derivatives of the objective function).Return the objective Gradients(derivatives of the objective function). Return the objective
function value at vars=x*) function value at vars=x*)
FletcherLineSearch[x_,ds_,vars_,gradients_,objectiveFunc_]:= FletcherLineSearch[x_, ds_, vars_, gradients_, objectiveFunc_]:=
Module[ Module[
{m,tau,rho,sigma,gamma,mhat,epsilon,xk,s,f0,gk,deltaf0,dk,aL,aU,fL,dfL, {m, tau, rho, sigma, gamma, mhat, epsilon, xk, s, f0, gk, deltaf0, dk, aL, aU, fL, dfL,
a0,a0hat,a0Lhat,a0Uhat,gtemp,df0,deltaa0,alpha,div}, a0, a0hat, a0Lhat, a0Uhat, gtemp, df0, deltaa0, alpha, div},
m=0; m=0;
sigma=0.1; sigma=0.1;
tau=Min[sigma,0.1]:(*tau<=sigma and tau<=0.1*) tau=Min[sigma, 0.1]: (*tau<=sigma and tau<=0.1*)
rho=sigma;(*rho<=slgma*) rho=sigma; (*rho<=slgma*)
gamma=0.75; gamma=0.75;
mhat=400; mhat=400;
epsilon=1.0*10^-10; Epsilon=1.0*10^-10;
xk=x;(*xk is a column vector*) xk=x; (*xk is a column vector*)
s=ds;(*′s′a column vector*) s=ds; (*'s'a column vector*)
Page13 Page13
Slavin.txt Slavin.txt
(*step 1: evaluate fk and gk at k=0.f0 is a scalar,g0 is a column (*step 1: evaluate fk and gk at k=0.f0 is a scalar,g0 is a column
vector*) vector*)
f0=ObjectiveFunc[xk,vars,objectiveFunc]; f0 = ObjectiveFunc[xk, vars, objectiveFunc];
gk=GradFunc[xk,vars,gradients];(*gk is acolumn vector*) gk = GradFunc[xk, vars, gradients]; (*gk is a column vector*)
m+=2; m+=2;
deltaf0=f0; deltaf0=f0;
(*step2:initialize the search*) (*step2:initialize the search*)
dk=s;(*dk is a column vector*) dk=s; (*dk is a column vector*)
aL=0.0; aL=0.0;
aU=1.0**10^99; aU=1.0**10^99;
fL=f0; fL=f0;
dfL=(Trranspose[gk].dk)[[1]][[1]]; dfL=(Trranspose[gk].dk)[[1]][[1]];
If[Abs[dfL]>epsilon, If[Abs[dfL]>epsilon,
If[div==0.0, If[div==0.0,
Print[″FletcherLineSearch divide by dfL=0.0″]; Print[″FletcherLineSearch divide by dfL=0.0″];
Abort[]; Abort[];
]; ];
a0=-2.0*deltaf0/dfL; a0=-2.0*deltaf0/dfL;
, ,
a0=1.0; a0=1.0;
]; ];
If[(a0×10^-9)||(a0>1.0), If[(a0×10^-9)||(a0>1.0),
a0=1.0; a0=1.0;
]; ];
(*step3: *) (*step3: *)
While[True, While[True,
deltak=a0*dk;(*deltak is a column vector*) deltak=a0*dk; (*deltak is a column vector*)
f0=ObjectiveFunc[xk+deltak,vars,objectiveFunc]; f0 = ObjectiveFunc[xk+deltak, vars, objectiveFunc];
m+=1; m+=1;
If[(f0>(fL+rho*(a0-aL)*dfL))&& If[(f0>(fL+rho*(a0-aL)*dfL))&&
(Abs[fL-f0]>epsilon)&&(m<mhat), (Abs[fL-f0]>epsilon)&&(m<mhat),
If[a0<aU, If[a0<aU,
aU=a0; aU=a0;
]; ];
div=2.0*(fL-f0+(a0-aL)*dfL); div=2.0*(fL-f0+(a0-aL)*dfL);
If[div==0.0, If[div==0.0,
Print[″FletcherLineSearch divide by div=0.0″]; Print[″FletcherLineSearch divide by div=0.0″];
Abort[]; Abort[];
]; ];
a0hat=aL+(dfL*(a0-aL)^2)/div; a0hat=aL+(dfL*(a0-aL)^2)/div;
a0Lhat=aL+tau*(aU-aL); a0Lhat=aL+tau*(aU-aL);
If[a0hat<a0Lhat, If[a0hat<a0Lhat,
a0hat=a0Lhat; a0hat=a0Lhat;
]; ];
a0Uhat=aU-tau*(aU-aL); a0Uhat=aU-tau*(aU-aL);
If[a0hat>a0Uhat, If[a0hat>a0Uhat,
a0hat=a0Uhat; a0hat=a0Uhat;
]; ];
a0=a0hat; a0=a0hat;
(*else*) (*else*)
(*gtemp is a vector*) (*gtemp is a vector*)
gtemp=GradFunc[xk+a0*dk,vars,gradents]; gtemp = GradFunc[xk+a0*dk,vars,gradents];
df0=(Transpose[gtemp].dk)[[1]][[1]]; df0 = (Transpose[gtemp].dk)[[1]][[1]];
m+=1; m+=1;
If[(df0<sigma*dfL)&&(Abs[fL-f0]>epsilon)&& If[(df0<sigma*dfL)&&(Abs[fL-f0]>epsilon)&&
(m<mhat)&&(dfL!=df0), (m<mhat)&&(dfL!=df0),
div=dfL-df0; div = dfL-df0;
deltaa0=(a0-aL)*df0/div; deltaa0=(a0-aL)*df0/div;
If[deltaa0<=0, If[deltaa0<=0,
a0hat=2*a0; A0hat=2*a0;
,(*else*) , (*else*)
a0hat=a0+deltaa0; A0hat=a0+deltaa0;
]; ];
Page14 Page14
Slavin.txt Slavin.txt
a0Uhat=a0+gamma*(aU-a0); a0Uhat=a0+gamma*(aU-a0);
If[a0hat>a0Uhat, If[a0hat>a0Uhat,
a0hat=a0Uhat; A0hat=a0Uhat;
]; ];
aL=a0; aL=a0;
a0=a0hat; A0=a0hat;
fL=f0; fL=f0;
dfL=df0; dfL=df0;
,(*else*) , (*else*)
Break[]; Break[];
]; ];
]; ];
]; ];
If[a0<1.0*10^-5, If[a0<1.0*10^-5,
alpha=1.0*10^-5; alpha=1.0*10^-5;
,(*else*) , (*else*)
alpha=a0; alpha=a0;
]; ];
Return[alpha]; Return[alpha];
] ]
FTSize[len_,min_]:= FTSize[len_,min_]:=
Module[ Module[
{}, {},
Return[Max[min,2^Ceiling[Log[2,len]]]]; Return[Max[min, 2^Ceiling[Log[2,len]]]];
] ]
Gaussian[mean_,sd_]:= Gaussian[mean_, sd_] :=
Module[ Module[
{result}, {result},
Return[sd*Sqrt[2.0]*InverseErf[Random[]]*Sign[Random[]-0.5]+mean]; Return[sd*Sqrt[2.0]*InverseErf[Random[]]*Sign[Random[]-0.5]+mean];
] ]
(*finds sample delay as a function of frequency. (*finds sample delay as a function of frequency.
uses ALL′list′taps-no symmetry is assumed*) uses ALL'list'taps-no symmetry is assumed*)
GenDelay[list_,min_:16]:= GenDelay[list_,min_:16]:=
Module[ Module[
{len,delays,endindex,nx}, {len, delays, endindex, nx},
len=Length[list]; len=Length[list];
nx=FTSize[len,min]; `nx=FTSize[len,min];
endindex=nx/2; endindex=nx/2;
Return[Take[Delays[list,nx],{1,endindex+1}]]; Return[Take[Delays[list,nx],{1,endindex+1}]];
] ]
(* (*
*distort the data for a particular filter order Length[taps]. *distort the data for a particular filter order Length[taps].
*) *)
GenDistortion[data_,taps_]:= GenDistortion[data_, taps_] :=
Module[ Module[
{len,filters,flen,delay,output,i,file}, {len, filters, flen, delay, output, i, file},
len=Length[data]; len=Length[data];
filters=Length[taps]; filters = Length[taps];
flen=Length[taps[[1]]]; flen = Length[taps[[1]]];
If[EvenQ[flen], If[EvenQ[flen],
Print[″Filter lengths are not all odd.″]; Print["Filter lengths are not all odd."];
Abort[]; Abort[];
]; ];
For[i=1,i<=taps1,++i, For[i=1, i<=taps1, ++i,
len1=Length[taps[[i]]]; len1=Length[taps[[i]]];
Page15 Page15
Slavin.txt Slavin.txt
If[len1!=flen, If[len1! =flen,
Print[″Filter lengths are not all equal.″]; Print["Filter lengths are not all equal."];
Abort[]; Abort[];
]; ];
]; ];
delay=(1+flen)/2; delay=(1+flen)/2;
output=Table[1.0,{len-flen+1}]; output = Table[1.0, {len-flen+1}];
For[i=1,i<=filters,++i, For[i=1, i<=filters, ++i,
filt=taps[[i]]; filt = taps[[i]];
If[Length[filt]!=flen, If[Length[filt]! =flen,
Print[″Filter lengths are not all the same.″]; Print["Filter lengths are not all the same."];
Abort[]; Abort[];
]; ];
output*=ListConvolve[filt,data]; output*=ListConvolve[filt, data];
]; ];
Return[output]; Return[output];
] ]
(*generate a set of filters for a particular order of distortion*) (*generate a set of filters for a particular order of distortion*)
GenFilters[len_,order_,spread_]:= GenFilters[len_, order_, spread_]:=
Module[ Module[
{error,taps,i,j,c}, {error, taps, i, j, c},
error=False; error=False;
If[!IntegerQ[len], If [! IntegerQ[len],
Print[″Filter lengths are not integer.″]; Print[″Filter lengths are not integer.″];
error=True; error=True;
]; ];
If[!OddQ[len], If [! OddQ[len],
Print[″Filter lengths are not odd.″]; Print["Filter lengths are not odd."];
error=True; error=True;
]; ];
If[error, If[error,
Abort[]; Abort[];
]; ];
c=(len+1)/2; c = (len+1)/2;
taps=Table[Gaussian[0,1]*ExpFunc[-Abs[(j-c)*2/spread]], Taps=Table[Gaussian[0,1]*ExpFunc[-Abs[(j-c)*2/spread]],
{i,1,order},{j,1,len}]; {i, 1, order}, {j, 1, len}];
Return[taps]; Return[taps];
] ]
(* (*
*′samples′gives nr of output sampels(plus extra),and also fundamental *'samples' gives nr of output sampels(plus extra), and also fundamental
*length,so all generated sines are harmonics of the fundamental. *length, so all generated sines are harmonics of the fundamental.
*′extra′gives the number of extra samples in the output record that may be *′extra′gives the number of extra samples in the output record that may be
*needed to compensate for convolution data loss due to filters. *needed to compensate for convolution data loss due to filters.
*′freqLo′is the low normalized frequency for sine output: *′freqLo′is the low normalized frequency for sine output:
*0<freqLow<0.5.The nearest higher harmonic of the′samples′frequency *0<freqLow<0.5.The nearest higher harmonic of the'samples'frequency
*is the lowest output frequency. *is the lowest output frequency.
*′freqHi′is the high normalized frequency for sine output: *′freqHi′is the high normalized frequency for sine output:
*0<freqLow<0.5.The nearest lower harmonic of the′samples′frequency *0<freqLow<0.5.The nearest lower harmonic of the'samples'frequency
*is the higheest output frequency. *is the highest output frequency.
*′freqInterval′is the normalized frequency step,also a harmonic of the *'freqInterval'is the normalized frequency step, also a harmonic of the
*′samples′frequency. *‘samples’frequency.
*) *)
GenTest[samples_,extra_,freqLo_,freqHi_,freqInterval_]:= GenTest[samples_, extra_, freqLo_, freqHi_, freqInterval_]: =
Module[ Module[
{kInterval,kStart,kEnd,sum,x,j,t}, {kInterval, kStart, kEnd, sum, x, j, t},
kInterval=Floor[freqInterval*samples+0.5]; kInterval=Floor[freqInterval*samples+0.5];
Page16 Page16
Slavin.txt Slavin.txt
kStart=Ceiling[freqLo*samples]; kStart = Ceiling[freqLo*samples];
kEnd=Floor[freqHi*samples]; kEnd = Floor[freqHi*samples];
sum=0; sum=0;
x=2.0*Pi/samples; x=2.0*Pi/samples;
For[j=kStart,j<=kEnd,j+=kInterval, For[j=kStart, j<=kEnd, j+=kInterval,
sum+=Table[sin[x*j*t],{t,0,samples+extra-1}]; sum+=Table[sin[x*j*t], {t, 0, samples+extra-1}];
]; ];
Return[sum]; Return[sum];
] ]
(*′x′is a 2-D column vector,′vars′is a list of variables in the list of (*′x′is a 2-D column vector,′vars′is a list of variables in the list of
′gradients′functions which are the partial derivatives of the objective ′gradients′functions which are the partial derivatives of the objective
function with respect to each variable.*) function with respect to each variable.*)
GradFunc[x_,vars_,gradients_]:= GradFunc[x_, vars_, gradients_] :=
Module[ Module[
{g,subst,j,len}, {g, subst, j, len},
len=Length[x]; len=Length[x];
subst=Table[vars[[j]]->x[[j]][[1]],{j,1,len}]; Subst = Table[vars[[j]]->x[[j]][[1]],{j,1,len}];
g=gradients/.subst; g = gradients/.subst;
Return[Transpose[{g}]];(*return a column vector as a 2-D matrix*) Return[Transpose[{g}]]; (*return a column vector as a 2-D matrix*)
] ]
IsSame[xx_]:= IsSame[xx_]:=
Module[ Module[
{nrVars,order,indices,permArray,perms,same,i,j,perm,v0,v1} {nrVars, order, indices, permArray, perms, same, i, j, perm, v0, v1}
nrVars=Length[xx]; nrVars = Length[xx];
order=(nrVars-1)/2; order=(nrVars-1)/2;
indices=Table[i,{i,1,order}]; indices = Table[i,{i,1,order}];
permArray=Permutations[indices]; permArray = Permutations[indices];
perms=Length[permArray]; perms = Length[permArray];
same=False; same=False;
For[j=1,j<=perms,++j, For[j=1, j<=perms, ++j,
perm=permArray[[j]]; Perm = permArray[[j]];
v0=perm[[1]]; v0 = perm[[1]];
v1=pem[[2]]; v1 = pem[[2]];
If[v1×v0, If[v1×v0,
same=(Chop[xx[[v0+order+1]]-xx[[v1+order+1]]]==0); Same=(Chop[xx[[v0+order+1]]-xx[[v1+order+1]]]==0);
If[same, If[same,
Break[]; Break[];
]; ];
]; ];
]; ];
Return[same]; Return[same];
] ]
Log10List[list_]:= Log10List[list_]:=
Module[ Module[
{minv,lminv,log,i,item,L,result}, {minv, lminv, log, i, item, L, result},
L=Length[list]; L = Length[list];
minv=Min[list]; minv=Min[list];
If[minv<=10^-10, If[minv<=10^-10,
minv=10^-10; minv = 10^-10;
]; ];
result=TaBle[0,{L}]; result = TaBle[0,{L}];
For[i=0,i<L,++i, For[i=0, i<L, ++i,
item=list[[i+1]]; item = list[[i+1]];
If[item<minv, If[item<minv,
item=minv; `item=minv;`
]; ];
result[[i+1]]=20.0 Log[10,item] result[[i+1]]=20.0 Log[10, item]
Page17 Page17
Slavin.txt Slavin.txt
]; ];
Return[result]; Return[result];
] ]
LogFFT[list_]:= LogFFT[list_]:=
[Mdule[ [Mdule[
{i,L,magfreg,logmagf,data,bins}, {i, L, magfreg, logmagf, data, bins},
L=Length[list]; L = Length[list];
bins=Floor[(L+1)/2]; bins=Floor[(L+1)/2];
magfreq=Abs [Take[Fourier[list,{FourierParameters->{-1,1}}],bins]]; magfreq = Abs[Take[Fourier[list, {FourierParameters->{-1, 1}}], bins]];
freq=Table[N[i/L],{i,0,bins-1}]; freq=Table[N[i/L], {i, 0, bins-1}];
logmagf=Log10List[magfreq]; ` logmagf = Log10List[magfreq];
data=Transpose[{freq,logmagf}]; data = Transpose[{freq, logmagf}];
Return[data]; Return[data];
] ]
Magnitude[list_,n_]:= Magnitude[list_,n_]:=
Module[ Module[
{i,L,reals,magfreq}, {i, L, reals, magfreq},
L=Length[list]; L = Length[list];
reals=Join[list,Table[0,{i,1,n-L}]]; Reals=Join[list, Table[0, {i, 1, n-L}]];
magfreq=Abs[Take[Fourier[reals,{FourierParameters->{1,1}}],n/2+1]]; magfreq = Abs[Take[Fourier[reals, {FourierParameters->{1, 1}}], n/2+1]];
Return[magfreq]; Return[magfreq];
] ]
(* (*
*patt1 and patt2 numeric list lengths are equal.Find the permutation index *patt1 and patt2 numeric list lengths are equal.Find the permutation index
*of patt2 that minimizes the sum of the squares of the differences of patt1 *of patt2 that minimizes the sum of the squares of the differences of patt1
*and patt2,modulo:'mod’.-Used for reorganizing phases.Also returns a *and patt2, modulo: 'mod'.-Used for reorganizing phases. Also returns a
*modified version of patt2 which is close to patt1,modulo′mod′。 *modified version of patt2 which is close to patt1, modulo 'mod'. the
*For example: *For example:
*MatchMod[{0.2,0.5,0.8},{1.22,0.88,0.47},1] *MatchMod[{0.2, 0.5, 0.8}, {1.22, 0.88, 0.47}, 1]
*yields the indicesmodified patt2,and odd status: *yields the indicesmodified patt2, and odd status:
*{{1,3,2},{0.22,0.47,0.88},False} * {{1, 3, 2}, {0.22, 0.47, 0.88}, False}
*) *)
MatchMod[patt1_,patt2_,mod_]:= MatchMod[patt1_,patt2_,mod_]:=
Module[ Module[
{len1,len2,indices,permArra,perms,min,sum,perm,i,j,diff,index,x,new, {len1, len2, indices, permArra, perms, min, sum, perm, i, j, diff, index, x, new,
step,steps,total,odd}, step, steps, total, odd},
len1=Length[patt1]; len1=Length[patt1];
len2=Length[patt2]; len2=Length[patt2];
If[len1!=len2, If[len1! =len2,
Print[″Length mismatch.″]; Print["Length mismatch."];
Abort[]; Abort[];
]; ];
indices=Table[i,{i,1,len1}] indices=Table[i, {i, 1, len1}]
permArray=Permutations[indices]; permArray = Permutations[indices];
perms=Length[permArray]; perms = Length[permArray];
min=Infinity; min=Infinity;
step=mod*0.5; step=mod*0.5;
For[j=1,j<=perms,++j, For[j=1, j<=perms, ++j,
sum=0; sum=0;
perm=permArray[[j]]; Perm = permArray[[j]];
total=0; total=0;
For[i=1,i<=len1,++i, For[i=1, i<=len1, ++i,
diff=patt1[[i]]-patt2[[perm[[i]]]]; diff = patt1[[i]]-patt2[[perm[[i]]]];
steps=Floor[diff/step+0.5]; steps = Floor[diff/step+0.5];
total+=steps; total+=steps;
sum+=(diff-step*steps)^2; sum+=(diff-step*steps)^2;
Page18 Page18
Slavin.txt Slavin.txt
]; ];
If[sum<min, If[sum<min,
(*found best solution so far*) (*found best solution so far*)
odd=OddQ[total;(*record the odd-ness of the solution*) odd=OddQ[total; (*record the odd-ness of the solution*)
index=j; index=j;
min=sum; min=sum;
]; ];
]; ];
perm=permArray[[index]]; perm = permArray[[index]];
new=Table[x=patt2[[perm[[i]]]]; new=Table[x=patt2[[perm[[i]]]];
x+step*Floor[(patt1[[i]]-x)/step+0.5], x+step*Floor[(patt1[[i]]-x)/step+0.5],
{i,1,len1}]; {i,1,len1}];
Return[{perm,new,odd}]; Return[{perm, new, odd}];
] ]
(*′x′is a 2-D column vector,′vars′is a list of all variables in the (*′x′is a 2-D column vector,′vars′is a list of all variables in the
objective function.Return the objective function value at vars=x*) Objective function.Return the objective function value at vars=x*)
ObjectiveFunc[x_,vars_,objectiveFunc_]:= ObjectiveFunc[x_, vars_, objectiveFunc_] :=
Module[ Module[
{subst,j,len}, {subst, j, len},
len=Length[x]; len=Length[x];
subst=Table[vars[[j]]->x[[j]][[1]],{j,1,len}]; Subst = Table[vars[[j]]->x[[j]][[1]],{j,1,len}];
Return[objectiveFunc/:subst];(*return a scalar*) Return[objectiveFunc/:subst]; (*return a scalar*)
] ]
PlotColor[list_,color_]:= PlotColor[list_, color_]:=
Module[ Module[
{min,max,r,g,b,data}, {min, max, r, g, b, data},
r=color[[1]]; r = color[[1]];
g=color[[2]]; g = color[[2]];
b=color[[3]]; b = color[[3]];
data={0,Transpose[list][[2]]};*always include zero*) data={0,Transpose[list][[2]]};*always include zero*)
max=Max[data]; max = Max[data];
min=Min[data]; min=Min[data];
Return[ListPlot[list,{PlotJoined->True, Return[ListPlot[list, {PlotJoined->True,
GridLines->Automatic, GridLines->Automatic,
PlotRange->{min,max}, PlotRange->{min,max},
ImageSize->600, ImageSize->600,
PlotStyle->RGBColor[r,g,b]}]]; PlotStyle->RGBColor[r,g,b]}]];
] ]
(*startIndex and endIndex indices(0-based)apply to the list*) (*startIndex and endIndex indices(0-based)apply to the list*)
plotFreq[list_,startIndex_:0,endIndex_:-1]:= plotFreq[list_, startIndex_:0, endIndex_:-1]:=
Module[ Module[
{i,L,delays,freq,data,idata,endi,max,min,selected}, {i, L, delays, freq, data, idata, endi, max, min, selected},
L=Length[list]; L = Length[list];
If[endIndex==-1, If[endIndex==-1,
endi=L-1, endi=L-1,
endi=endIndex endi=endIndex
]; ];
freq=Table[N[i/(2*(L-1))],{i,startIndex,endi}]; freq=Table[N[i/(2*(L-1))], {i, startIndex, endi}];
selected=Take[list,{startIndex+1,endi+1}]; selected = Take[list, {startIndex+1, endi+1}];
data=Transpose[{freq,selected}]; data = Transpose[{freq, selected}];
idata={0,selected};(*always include zero*) idata={0, selected}; (*always include zero*)
max=Max[idata]; max = Max[idata];
min=Min[idata]; min=Min[idata];
Return[ListPlot[data,{PlotJoined->True, Return[ListPlot[data,{PlotJoined->True,
GridLines->Automatic, GridLines->Automatic,
PlotRange->{{0,0.5},{min,max}}, PlotRange->{{0,0.5},{min,max}},
ImageSize->600, ImageSize->600,
Page19 Page19
Slavin.txt Slavin.txt
PlotStyle->RGBColor[1,0,0]}]]; PlotStyle->RGBColor[1, 0, 0]}]];
] ]
(*finds sample delay as a function of frequency. (*finds sample delay as a function of frequency.
uses ALL ′list′taps -no symmetry is assumed,plot in red*) uses ALL 'list' taps -no symmetry is assumed,plot in red*)
PlotRawDelay[delays_]:= PlotRawDelay[delays_]:=
Module[ Module[
{i,len,freq,data}, {i, len, freq, data},
len=Length[delays]-1; len=Length[delays]-1;
freq=Table[N[i/(2*len)],{i,0,len}]; freq=Table[N[i/(2*len)], {i, 0, len}];
data=Transpose[{freq,delays}]; data = Transpose[{freq, delays}];
Return[PlotColor[data,{1,0,0}]]; Return[PlotColor[data,{1,0,0}]];
] ]
PlotUnwindowedFFT[list_]:= PlotUnwindowedFFT[list_]:=
Module[ Module[
{}, {},
Return[WfmColor[LogFFT[list],{1,0,0}]]; Return[WfmColor[LogFFT[list],{1,0,0}]];
] ]
PolarToComplex[ampls_,angles_]:= PolarToComplex[ampls_, angles_]:=
Module[ Module[
{l1,l2,fl,i,len,reals,angle,ampl,real,imag,out}, {l1, l2, fl, i, len, reals, angle, ampl, real, imag, out},
l1=Length[ampls]; l1=Length[ampls];
l2=Length[angles]; l2=Length[angles];
If[l1!=l2, If[l1! = l2,
Print[″Missmatched amplitude and angle list lengths.″]; Print["Missmatched amplitude and angle list lengths."];
Abort[]; Abort[];
]; ];
len=l1-1; len=l1-1;
fl=2*len; `fl=2*len;
out=Table[0,{i,1,fl}]; out = Table[0,{i,1,fl}];
For[i=0,i×len,++i, For[i=0, i×len, ++i,
angle=angles[[i+1]]; angle = angles[[i+1]];
ampl=ampls[[i+1]]; ampl = ampls[[i+1]];
real=ampl Cos[angle]; real = ampl Cos[angle];
imag=ampl Sin[angle]; imag = ampl Sin[angle];
out[[i+1]]=real+I imag; out[[i+1]]=real+I imag;
If[(i !=0), If[(i != 0),
out[[fl-i+1]]=real-I imag; out[[fl-i+1]]=real-I imag;
]; ];
]; ];
out[[len+1]]=ampls[[len+1]]; out[[len+1]]=ampls[[len+1]];
Return[out]; Return[out];
] ]
PrAmplPhase[data_,bin_]:= PrAmplPhase[data_, bin_]:=
Module[ Module[
{out,ampl,ph}, {out,ampl,ph},
out=DFT[data,bin]; out = DFT[data, bin];
ampl=Abs[out]; ampl = Abs[out];
ph=Arg[out]; ph = Arg[out];
Return[{ampl,ph}]; Return[{ampl,ph}];
] ]
ProcessCalData[data_,order_,lowf_,hiF_,acc_]:= ProcessCalData[data_, order_, lowf_, hiF_, acc_]: =
Module[ Module[
{fi, {fi,
Page20 Page20
Slavin.txt Slavin.txt
delta,freqs,start,end,skip,i,j,t,freqIndex,overhang, delta, freqs, start, end, skip, i, j, t, freqIndex, overhang,
i1,i2,ampl,ph,len,bins,sBins,w1,w2,scaling,temp,cycle, i1, i2, ampl, ph, len, bins, sBins, w1, w2, scaling, temp, cycle,
amplRet,phRef,amplRatio,q,scale, amplRet, phRef, amplRatio, q, scale,
amplitude2,relPhase2,relDelay2,amplitude3,relPhase3,relDelay3, amplitude2, relPhase2, relDelay2, amplitude3, relPhase3, relDelay3,
corrPh,turns,rph,xbin,analyze1,reference,redo,d1,d2,x,y, corrPh, turns, rph, xbin, analyze1, reference, redo, d1, d2, x, y,
dly,dlyA,dlyB,amplA,amplB,donesomething, dly, dlyA, dlyB, amplA, amplB, donesomething,
descr,expected,K,logSize,logFregs,amplx, descr, expected, K, logSize, logFregs, amplx,
magA,magB,partAm1,partAp1,partBm1,partBp1,transpose, magA, magB, partAm1, partAp1, partBm1, partBp1, transpose,
delays,base,partial,de,amplI,ii,nrBins, delays, base, partial, de, amplI, ii, nrBins,
filter1,filter2,frBins,index,f1,f2,fs,out1,out2,out3, filter1, filter2, frBins, index, f1, f2, fs, out1, out2, out3,
e2,g,s,nrVars,symbolicBins,symbVars, e2, g, s, nrVars, symbolicBins, symbVars,
k,a,d,ix,sx,xnew,yl,allSymBins,blen,slen,numericBins, k, a, d, ix, sx, xnew, yl, allSymBins, blen, slen, numericBins,
dfts,dft,results,maxorde,gainA,gainB,delavA,delayB, dfts, dft, results, maxorde, gainA, gainB, delavA, delayB,
maxIterations,substx,jj,kk,random, maxIterations, substx, jj, kk, random,
residual,lowestResiduals,bestResults,startPoints,xStart,gains, residual, lowestResiduals, bestResults, startPoints, xStart, gains,
solutions,found,xx,qresults,solution,smallesttResidueIndex, solutions, found, xx, qresults, solution, smallesttResidueIndex,
sortList,sorted,state,const,maxTries,extraTries, sortList, sorted, state, const, maxTries, extraTries,
symbvarsW,symbolicBinsW,e2W,gW,dftsW}, symbvarsW, symbolicBinsW, e2W, gW, dftsW},
Print[″*******************************************************″]; Print[″*************************************** ********"];
Print[″****************** initialization *********************″]; Print
Print[″*******************************************************″]; Print[″*************************************** ********"];
(*Various″magic″parameters*) (*Various″magic″parameters*)
(*maximum tries to find a first BFGS solution.Too large means time (*maximum tries to find a first BFGS solution. Too large means time
may be wasted finding a solution when none can be found.Too small may be wasted finding a solution when none can be found. Too small
and a solution may not be found.*) and a solution may not be found.*)
maxTries=100; maxTries=100;
(*extra attempts to find more BFGS solutions after the first is found. (*extra attempts to find more BFGS solutions after the first is found.
Too large and time may be wasted finding additional solutions when Too large and time may be wasted finding additional solutions when
none exist. Too small,and a better solution can be missed.The None exist. Too small, and a better solution can be missed.The
probability of missing a second solution is about 1/2 per try, Probability of missing a second solution is about 1/2 per try,
so the probability of missing it is(1/2)^extraTries*) So the probability of missing it is(1/2)^extraTries*)
extraTries=25; extraTries = 25;
(*maximum BFGS iterations allowed in which to converge to a solution. (*maximum BFGS iterations allowed in which to converge to a solution.
Too large and time may be wasted trying to find a BFGS solution, Too large and time may be wasted trying to find a BFGS solution,
too small and a solution may not be found.Typically,2nd order too small and a solution may not be found.Typically, 2nd order
needs<30 and 3rd order needs<80.*) needs<30 and 3rd order needs<80.*)
maxIterations=100; maxIterations = 100;
(*maximum number of total unique solutions at a cal frequency. (*maximum number of total unique solutions at a cal frequency.
2nd order:3^2=9 solutions per group,3rd order:3^3=27 per group. 2nd order: 3^2=9 solutions per group, 3rd order: 3^3=27 per group.
Too larg a value and more memory is used.Too small and there is Too larg a value and more memory is used. Too small and there is
insufficient storage for multiple groups.I′ve never seen more than 3 Insufficient storage for multiple groups. I′ve never seen more than 3
groups,or 3*27=81 solutions for any frequency.*) groups, or 3*27=81 solutions for any frequency.*)
solutions=200; solutions=200;
(*sampling frequency(MHz)*) (*sampling frequency(MHz)*)
fs=100.0; fs=100.0;
overhang=63; overhang=63;
logFreqs=7; logFreqs=7;
symbVars= symbVars =
Flatten[{k,Table[a[j],{j,1,order}],Table[d[j],{j,1,order}]}]; Flatten[{k, Table[a[j], {j, 1, order}], Table[d[j], {j, 1, order}]}];
{symbolicBins,e2,g,dfts}=DoInit[stmbvars,ix,sx,dft]; {symbolicBins, e2, g, dfts} = DoInit[stmbvars, ix, sx, dft];
If[(lowF<0)||(lowF>0.5)||(hiF<0)||(hiF>0.5)|| If[(lowF<0)||(lowF>0.5)||(hiF<0)||(hiF>0.5)||
(lowF>=hiF), (lowF>=hiF),
Print[″low or high frequency bounds are<0 or×0.5,or″]; Print[″low or high frequency bounds are<0 or×0.5, or″];
Print[″low frequency bound″,lowF,″is>=hidh bound″,hiF]; Print["low frequency bound", lowF, "is>=hidh bound", hiF];
Abort[]; Abort[];
]; ];
Print[″sampling frequency:″,fs,″MHz″]; Print["sampling frequency:", fs, "MHz"];
logSize=logFreqs+3;(*added value must be>=3*) logSize=logFreqs+3; (*added value must be>=3*)
Page21 Page21
Slavin.txt Slavin.txt
delta=1; delta=1;
samples=2^logSize;(*power of 2*) samples=2^logSize; (*power of 2*)
n=(2*overhang+1);(*n is odd filter length*) n=(2*overhang+1); (*n is odd filter length*)
len=samples+2*(n-1);(*overhang required at each end*) len=samples+2*(n-1); (*overhang required at each end*)
If[logFreqs>logSize-3, If[logFreqs>logSize-3,
Print[″logFreqs must be<=logSize-3″]; Print[″logFreqs must be<=logSize-3″];
Abort[]; Abort[];
]; ];
freqs=2^logFregs;(*frequencies to Nyguist. A power of 2*) freqs=2^logFregs; (*frequencies to Nyguist. A power of 2*)
start=Max[Floor[lowF*freqs*2],1]; start=Max[Floor[lowF*freqs*2], 1];
end=Min[Ceiling[hiF*freqs*2],freqs-1]; end=Min[Ceiling[hiF*freqs*2], freqs-1];
If[start==freqs/2, If[start==freqs/2,
Print[″Error:start frequency evaluates to fs/2.This cannot be″ Print[″Error: start frequency evaluates to fs/2.This cannot be″
″used because it starts on an alias notch.″]; "used because it starts on an alias notch."];
Abort[]; Abort[];
]; ];
If[end==freqs/2, If[end==freqs/2,
Print[″Error:end frequency evaluates to fs/2.This cannot be″ Print[″Error: end frequency evaluates to fs/2.This cannot be″
″used because it starts on an alias notch.″]; "used because it starts on an alias notch."];
Abort[]; Abort[];
]; ];
skip=samples/(2*freqs); skip=samples/(2*freqs);
Print[″Frequency indices:start=″,start,″,end=″,end]; Print["Frequency indices: start = ", start, ", end = ", end];
Print[″Range:0:″,freqs-1,″,index skip=″,skip]; Print["Range:0:", freqs-1, ", index skip=", skip];
(*nr of different IM and harmonic frequency bins to consider*) (*nr of different IM and harmonic frequency bins to consider*)
nrBins=Length[symbolicBins]; nrBins = Length[symbolicBins];
amplitude=Table[0,{i,1,freqs+1},{j,1,nrBins}]; amplitude=Table[0, {i, 1, freqs+1}, {j, 1, nrBins}];
yl=Table[0,{i,1,freqs+1},{j,1,nrBins}]; yl=Table[0,{i,1,freqs+1},{j,1,nrBins}];
bins=Table[0,{i,1,freqs+qs+1},{j,1,nrBins}]; bins=Table[0,{i,1,freqs+qs+1},{j,1,nrBins}];
amplRatio=Table[0.0,{i,1,freqs+1}]; amplRatio=Table[0.0,{i,1,freqs+1}];
Scaling=Table[0.0,{i,1,freqs+1}]; Scaling=Table[0.0,{i,1,freqs+1}];
descr=Table[0.0,{i,1,freqs+1}]; descr=Table[0.0,{i,1,freqs+1}];
allSymBins=AllTerms[ii,orde]; allSymBins = AllTerms[ii, orde];
blen=Length[allSymBins]; blen = Length[allSymBins];
dly=0.0; dly=0.0;
redo=-1; redo=-1;
const=2*Pi/samples; const=2*Pi/samples;
Print[″*******************************************************″]; Print[″*************************************** ********"];
Print[″****************** DFT analysis ***********************″]; Print[″****************** DFT analysis***************************************************************
Print[″******************************************************″]; Print[″*************************************** *******"];
(* (*
*default x[[i]]=False indicates not measurable due to aliasing, *default x[[i]]=False indicates not measurable due to aliasing,
*True indicates measurable but failed to converge on search, *True indicates measurable but failed to converge on search,
*otherwise x[[i]]equals a list of solutions. *otherwise x[[i]]equals a list of solutions.
*) *)
x=Table[False,{i,1,freqs+1}]; x = Table[False, {i, 1, freqs+1}];
For[fi=start,fi<=end,++fi, For[fi=start, fi<=end, ++fi,
i=fi+1;(*offset for non-zero based array indexing*) i=fi+1; (*offset for non-zero based array indexing*)
index=freqs-fi; index = freqs-fi;
analyze1=data[[index]]; analyze1 = data[[index]];
freqIndex=fi skip; freqIndex = fi skip;
i1=freqIndex-delta; i1 = freqIndex-delta;
i2=freqIndex+delta; i2=freqIndex+delta;
w1=2*Pi*i1/samples; w1=2*Pi*i1/samples;
w2=2*Pi*i2/samples; w2=2*Pi*i2/samples;
Page 22 Page 22
Slavin.txt Slavin.txt
Print[″*****************************″]; Print[″****************************″];
Print[″fi=″,fi,″,index=″,index,″,freqIndex=″,freqIndex]; Print["fi=", fi, ", index=", index, ", freqIndex=", freqIndex];
(*look for alias collisions using all frequencies*) (*look for alias collisions using all frequencies*)
numericBins=allSymBins/.ii->freqIndex; numericBins = allSymBins/.ii->freqIndex;
sBins=Sort[AliasF[numericBins,samples]]; sBins = Sort[AliasF[numericBins, samples]];
Print[″sBins=″,sBins]; Print[″sBins=", sBins];
For[j=1,j<blen,++j, For[j=1, j<blen, ++j,
If[sBins[[j]]==sBins[[j+1]], If[sBins[[j]]==sBins[[j+1]],
redo=i; Redo = i;
Break[]; Break[];
]; ];
]; ];
If[redo==i, If[redo==i,
Continue[] Continue[]
]; ];
x[[i]]=True;(*indicate measurable at i*) x[[i]]=True; (*indicate measurable at i*)
(*symbolicBins represents only the frequencies used for analysis, (*symbolicBins represents only the frequencies used for analysis,
which excludes Dc and the ibput cal frequencies themselves*) which excludes Dc and the ibput cal frequencies themselves*)
bins[[i]]=symbolicBins/.ix->freqIndex; bins[[i]]=symbolicBins/.ix->freqIndex;
Print[″bins″,order,″=″,bins[[i]]]; Print[″bins″, order, ″=″, bins[[i]]];
(*generate timing references from signal+small distortion*) (*generate timing references from signal+small distortion*)
reference=analyze1^order; reference=analyze1^order;
temp=Abs[DFT[analyze1,i1]]; temp = Abs[DFT[analyze1, i1]];
temp+=Abs[DFT[analyze1,i2]]; temp+=Abs[DFT[analyze1,i2]];
scaling[[i]]=temp*0.5; scaling[[i]]=temp*0.5;
(*calculate amplitudes,phases and delays*) (*calculate amplitudes, phases and delays*)
For[j=1,j<=nrBins,++j, For[j=1, j<=nrBins, ++j,
xbin=bins[[i,j]]; xbin = bins[[i, j]];
temp=DFT[analyze1,xbin]; temp = DFT[analyze1, xbin];
{amplRef,phRef=PrAmplPhase[reference,xbin]; {amplRef, phRef = PrAmplPhase[reference, xbin];
yl[[i,j]]=temp*Exp[-I*phRef]; yl[[i,j]]=temp*Exp[-I*phRef];
]; ];
f1=N[fs*i1/samples,8]; f1=N[fs*i1/samples, 8];
f2=N[fs*i2/samles,8]; f2=N[fs*i2/samles, 8];
Print[″f1=″,fs-f1,″(aliased=″,f1,″),″, Print[″f1=", fs-f1,"(aliased=", f1,"), ",
″f1=″,fs-f2,″(aliased=″,f2,″).″]; ″f1=″, fs-f2, ″(aliased=″, f2,″).″];
Print[″yl[″,i,″]=″,yl[[i]]]; Print[″yl[″,i,″]=″,yl[[i]]];
If[redo==(i-1), If[redo==(i-1),
redo=-1; redo=-1;
]; ];
]; ];
Print[″**************************************************************″]; Print[″*************************************** ***************"];
Print[″************************** Optimization ***********************″]; Print[″********************************************** ***"];
Print[″**************************************************************″]; Print[″*************************************** ***************"];
search=1;(*related search radius*) search=1; (*related search radius*)
For[fi=start,fi<=end,++fi, For[fi=start, fi<=end, ++fi,
Print[″*****************************″]; Print[″****************************″];
i=fi+1;(*offset for non-zero based array indexing*) i=fi+1; (*offset for non-zero based array indexing*)
If[!x[[i]]; If [! x[[i]];
Continue[]; Continue[];
]; ];
Page23 Page23
Slavin.txt Slavin.txt
cycle=samples/freqIndex; cycle=samples/freqIndex;
(*measurable*) (*measurable*)
freqIndex=fi*skip; freqIndex = fi*skip;
Print[″fi=″,fi,″,freqIndex=″,freqIndex, Print["fi=", fi, ", freqIndex=", freqIndex,
″,cycl delay(samples)=″,N[cycle]]; ″, cycle delay(samples) = ″, N[cycle]];
Print[″y[″,fi,″]=″,yl[[i]]]; Print[″y[″, fi, ″]=″, yl[[i]]];
lowestResiduals=Table[Intinity,{solutions}]; lowestResiduals = Table[Intinity, {solutions}];
bestResults=Table[{},{solutions}]; bestResults = Table[{}, {solutions}];
startPoints=Table[{},{solutions}]; startPoints = Table[{},{solutions}];
solution=0; solution=0;
smallestResidueIndex=1; smallestResidueIndex = 1;
kk=maxTries; kk=maxTries;
nestStart={}; nestStart = {};
random=False; random=False;
While[--kk>=0, While[--kk>=0,
slen=Length[x[[i-1]]]; slen = Length[x[[i-1]]];
random=(slen==0)||(kk!=maxTries-1)||IsSame[x[[i-1]]]; random=(slen==0)||(kk!=maxTries-1)||IsSame[x[[i-1]]];
If[random, If[random,
If[slen==0, If[slen==0,
xStart=Flatten[ xStart=Flatten[
{0.1*(Random[]-0.5), {0.1*(Random[]-0.5),
Table[Exp[0.1*(Random[]-0.5)],{order}], Table[Exp[0.1*(Random[]-0.5)],{order}],
Table[cycle*(Random[]-0.5)*0.5,{order}]}]; Table[cycle*(Random[]-0.5)*0.5,{order}]}];
, , ,
xStart=x[[i-1]] xStart=x[[i-1]]
Table[Exp[0.4*(Random[]-0.5)],{slen}]; Table[Exp[0.4*(Random[]-0.5)],{slen}];
]; ];
, , ,
xStart=x[[i-1]]; xStart = x[[i-1]];
]; ];
{results,residual}=DoSolve[e2,g,dfts,symbVars, {results, residual} = DoSolve[e2, g, dfts, symbVars,
yl[[i]],xStart,sx, yl[[i]], xStart, sx,
samples,ix,freqIndex,acc, samples, ix, freqIndex, acc,
maxIterations]; maxIterations];
If[Length[results]<=0, If[Length[results]<=0,
Continue[]; Continue[];
]; ];
If[!random, If [! random,
Print[″result=″,results]; Print[″result=″,results];
Print[″residual=″,residual]; Print[″residual=″, residual];
x[[i]]=results; x[[i]]=results;
Break[]; Break[];
]; ];
(*center the angles as much as possible*) (*center the angles as much as possible*)
xStart=results; xStart = results;
parity=0; parity=0;
For[jj=1,jj<=order,++]], For[jj=1, jj<=order, ++]],
xx=Floor[[results[[order+jj+1]]*(2.0/cycle))+1/2]; xx=Floor[[results[[order+jj+1]]*(2.0/cycle))+1/2];
xStart[[order+jj+1]]-=(xx*cycle*0.5); xStart[[order+jj+1]]-=(xx*cycle*0.5);
parity+=xx; Parity+=xx;
]; ];
If[OddQ[parity], If[OddQ[parity],
xStart[[1]]=-xStart[[1]]; xStart[[1]]=-xStart[[1]];
]; ];
(*reoptimize from more centered starting point*) (*reoptimize from more centered starting point*)
{results,residual}=DoSolve[e2,g,dfts,symbVars, {results, residual} = DoSolve[e2, g, dfts, symbVars,
yl[[i]],xStart,sx, yl[[i]], xStart, sx,
samples,ix,freqIndex,acc, samples, ix, freqIndex, acc,
maxIterations]; maxIterations];
If[Length[results]<=0, If[Length[results]<=0,
Continue[]; Continue[];
Page24 Page24
Slavin.txt Slavin.txt
]; ];
sortList={Table[results[[jj+order+1]],{jj,1,order}], sortList={Table[results[[jj+order+1]], {jj, 1, order}],
Table[results[[jj+1]],{jj,1,order}], Table[results[[jj+1]],{jj,1,order}],
Table[xStart[[jj+order+1]],{jj,1,order}], Table[xStart[[jj+order+1]],{jj,1,order}],
Table[xStart[[jj+1]],{jj,1,order}]}: Table[xStart[[jj+1]], {jj, 1, order}]}:
(*rank solutions in order of second sub-list (angles)*) (*rank solutions in order of second sub-list (angles)*)
sorted=Transpose[Sort[Transpose[sortList]]]; sorted=Transpose[Sort[Transpose[sortList]]];
results=Flatten[{results[[1]],sorted[[2]],sorted[[1]]}]; results=Flatten[{results[[1]], sorted[[2]], sorted[[1]]}];
xStart=Flatten[{xStart[[1]],sorted[[4]],sorted[[3]]}]; xStart = Flatten[{xStart[[1]], sorted[[4]], sorted[[3]]}];
(*see if solution found already*) (*see if solution found already*)
found=False; found=False;
For[jj=1,jj<=solutions,++jj, For[jj=1, jj<=solutions, ++jj,
If[lowestResiduals[[jj]]==Infinity, If[lowestResiduals[[jj]]==Infinity,
(*reached end of valid solutions,nothing found*) (*reached end of valid solutions,nothing found*)
Break[]; Break[];
,(*else*) , (*else*)
If[Chop[lowestResiduals[[jj]]-residual]==0.0, If[Chop[lowestResiduals[[jj]]-residual]==0.0,
found=True; found=True;
Break[];(*solution already found*) Break[]; (*solution already found*)
]; ];
]; ];
]; ];
If[found, If[found,
Continue[]; Continue[];
]; ];
(*no solution found*) (*no solution found*)
If[jj>solutions, If[jj>solutions,
(*finding another solution when no more are allowed*) (*finding another solution when no more are allowed*)
Print[″*************************″, Print["************************",
″Too many solutions found.″, "Too many solutions found.",
″*************************″]; ″*************************″];
Abort[]; Abort[];
]; ];
(*new solution,so reset loop limit*) (*new solution, so reset loop limit*)
kk=extraTries; kk = extraTries;
(*find index into data set with lowest error residual*) (*find index into data set with lowest error residual*)
If[jj>1, If[jj>1,
If[residual<lowestResiduals[[smallestResidueIndex]], If[residual<lowestResiduals[[smallestResidueIndex]],
smallestResidueIndex=jj; The smallestResidueIndex = jj;
]; ];
]; ];
(*find a multiplicity of local solutions at approximately Pi (*find a multiplicity of local solutions at approximately Pi
intervals on all angles*) intervals on all angles*)
lowestResiduals[[jj]]=residual; lowestResiduals[[jj]]=residual;
bestResults[[jj]]=results; bestResults[[jj]]=results;
startPoints[[jj]]=xStart; startPoints[[jj]]=xStart;
++solution; ++solution;
Print[″Solution″,solution]; Print["Solution", solution];
Print[″Starting vector x=″,xStart]; Print[″Starting vector x=″, xStart];
Print[″Minimum at″,results]; Print["Minimum at", results];
Print[″Lowest residual error=″,residual]; Print[″Lowest residual error=″, residual];
++jj; ++jj;
state=Table[-search,{order}]; state=Table[-search,{order}];
While[True, While[True,
(*find next state*) (*find next state*)
xStart=results; xStart = results;
(*Print[″state=″,state];*) (*Print[″state=″, state];*)
parity=0; parity=0;
For[xx=1,xx<=order,++xx, For[xx=1, xx<=order, ++xx,
Page25 Page25
Slavin.txt Slavin.txt
parity+=state[[xx]]; Parity+=state[[xx]];
xStart[[order+1+xx]]+=(cycle*state[[xx]]*0.5); xStart[[order+1+xx]]+=(cycle*state[[xx]]*0.5);
]; ];
If[OddQ[parity], If[OddQ[parity],
xStart[[1]]=-results[[1]]; xStart[[1]]=-results[[1]];
]; ];
{qresults,residual}=DoSolve[e2,g,dfts,symbVars, {qresults, residual} = DoSolve[e2, g, dfts, symbVars,
y[[i]],xStart,sx, y[[i]], xStart, sx,
samples,ix,freqIndex,acc, samples, ix, freqIndex, acc,
maxIterations]; maxIterations];
If[Length[qresults]>0, If[Length[qresults]>0,
If[jj>solutions, If[jj>solutions,
Print[″*************************″,
″Too many solutions found.″, "Too many solutions found.",
″*************************″]; ″***********************″];
Abort[]; Abort[];
]; ];
lowestResiduals[[jj]]=residual; lowestResiduals[[jj]]=residual;
bestResults[[jj]]=qresults; BestResults[[jj]]=qresults;
startPoints[[jj]]=xStart; startPoints[[jj]]=xStart;
++jj; ++jj;
]; ];
xx=1; xx=1;
While[xx<=order, While[xx<=order,
state[[xx]]+=1; State[[xx]]+=1;
If[state[[xx]]<=search, If[state[[xx]]<=search,
Break[]; Break[];
]; ];
state[[xx]]=-search; State[[xx]]=-search;
++xx; ++xx;
]; ];
If[xx>order, If[xx>order,
Break[]; Break[];
]; ];
];(*end of While[True,]*) ]; (*end of While[True,]*)
];(*end of While[--k>=0,]*) ]; (*end of While[--k>=0,]*)
If[random, If[random,
If[Length[bestResults[[1]]]==0, If[Length[bestResults[[1]]]==0,
Print[″Solutions not found.″]; Print["Solutions not found."];
(*leave x[[i]]as True indicates measurable but not valid*) (*leave x[[i]] as True indicates measurable but not valid*)
x[[i]]=bestResults[[smallestResidueIndex]]; x[[i]]=bestResults[[smallestResidueIndex]];
]; ];
]; ];
]; ];
(* (*
*for each i,x[[i]] is either a legitimate list of solutions,or is *for each i, x[[i]] is either a legitimate list of solutions, or is
*boolean False indicating it is not measurable due to alias frequency *boolean False indicating it is not measurable due to alias frequency
*conflicts,or is True indicating it is measurable,but that a *conflicts, or is True indicating it is measurable, but that a
*solution hasn′t been previously tound. *solution hasn′t been previously toound.
*) *)
Print[″Filling in holes using search:″]; Print[″Filling in holes using search:″];
(*fill in holes where no solution was found*) (*fill in holes where no solution was found*)
doneSomething=True; doneSomething = True;
While[doneSomething, While[doneSomething,
doneSomething=FALSE; doneSomething = FALSE;
for[fi=start,fi<=end,++fi, for[fi=start, fi<=end, ++fi,
i=fi+1;(*offset for non-zero based array indexing*) i=fi+1; (*offset for non-zero based array indexing*)
If[(Length[x[[i]]]==0)&& x[[i]]], If[(Length[x[[i]]]==0)&& x[[i]]],
(*x[[i]]is measurable*) (*x[[i]] is measurable*)
freqIndex=fi*skip; freqIndex = fi*skip;
Page26 Page26
Slayin.txt Slayin.txt
If[(fi>start)&&(Length[x[[i-1]]]>0), If[(fi>start)&&(Length[x[[i-1]]]>0),
xStart=x[[i-1]]; xStart=x[[i-1]];
{results,residual}=DoSolve[e2,g,dfts,symbVars, {results, residual} = DoSolve[e2, g, dfts, symbVars,
yl[[i]],xStart,sx, yl[[i]],xStart,sx,
samples,ix,freqIndex,acc, samples, ix, freqIndex, acc,
maxIterations]; maxIterations];
If[Length[results]>0, If[Length[results]>0,
x[[i]]=results; x[[i]]=results;
doneSomething=True; doneSomething=True;
Print[″x[″,fi,″]=″,x[[i]]]; Print[″x[″,fi,″]=″,x[[i]]];
Print[″residual=″,residual]; Print[″residual=″, residual];
]; ];
]; ];
If[(Length[x[[i]]]==0)&& If[(Length[x[[i]]]==0)&&
(fi<end)&&(Length[x[[i+1]]]>0), ... (fi<end)&&(Length[x[[i+1]]]>0),
xStart=x[[i+1]]; xStart=x[[i+1]];
{results,residual}=DoSolve[e2,g,dtts,symbVars, {results, residual} = DoSolve[e2, g, dtts, symbVars,
yl[[i]],xStar,sx, yl[[i]],xStar,sx,
samples,ix,freqIndex, samples, ix, freqIndex,
acc,maxIterations]; acc, maxIterations];
If[Length[results]>0, If[Length[results]>0,
x[[i]]=results; x[[i]]=results;
doneSomething=True; doneSomething=True;
Print[″x[″,Fi,″]=″x[[i]]]; Print[″x[″,Fi,″]=″x[[i]]];
Print[″residual=″,residual]; Print[″residual=″,residual];
]; ];
]; ];
]; ];
]; ];
]; ];
Print[″Forcibly filling all renaining holes using previous valuesls:″]; Print[″Forcibly filling all renaining holes using previous valuesls:″];
For[fi=start+1,fi<=end,++fi, For[fi=start+1, fi<=end, ++fi,
i=fi+1;(*offset for non-zero based array indexing*) i=fi+1; (*offset for non-zero based array indexing*)
If[Lenth[x[[i]]]==0, If[Lenth[x[[i]]]==0,
x[[i]]=x[[i-1]]; x[[i]]=x[[i-1]];
]; ];
]; ];
Print[″Scale output values:″]; Print[″Scale output values:″];
(*scale as separate step to avoid problems with valid handling*) (*scale as separate step to avoid problems with valid handling*)
For[fi=start,fi<=end,++fi, For[fi=start, fi<=end, ++fi,
i=fi+1; i=fi+1;
If[scaling[[i]]==0.0, If[scaling[[i]]==0.0,
temp=(scaling[[i-1]]+scaling[[i+1]]*0.5; Temp = (scaling[[i-1]]+scaling[[i+1]]*0.5;
,
temp=scaling[[i]]; temp = scaling[[i]];
]; ];
x[[i,1]]/=(temp^order); x[[i,1]]/=(temp^order);
(*Print[″output:x[″,fi,″]=”,x[[i]]];*) (*Print[″output:x[″, fi,″]=", x[[i]]];*)
]; ];
Return[x]; Return[x];
] ]
(*finds amplitudes and delay (in sample units)response of even length real (*finds amplitudes and delay (in sample units) response of even length real
tap filter*) tap filter*)
Response[real]taps_]:= Response[real]taps_]:=
Module[ Module[
{taps,dcDelay,complex,len,l1,ampls,delays,i,ampl, {taps, dcDelay, complex, len, l1, ampls, delays, i, ampl,
radiansPerSample,delay,prevangle,angle,diffangle,newdelay,mod, radiansPerSample, delay, prevangle, angle, diffangle, newdelay, mod,
scale,xtaps}, scale, xtaps},
taps=Length[realtaps]; taps = Length[realtaps];
Page27 Page27
Slavin.txt Slavin.txt
(*Print[″realtaps=″,realtaps];*) (*Print[″realtaps=″,realtaps];*)
(*calculate the dc delay without Arg[] aliasing.*) (*calculate the dc delay without Arg[] aliasing.*)
dcDelay=DCdelay[realtaps]; dcDelay = DCdelay[realtaps];
(*extend input to scale*taps to use a longer FFT which (*extend input to scale*taps to use a longer FFT which
should reduce phase wrapping ambiguities*) should reduce phase wrapping ambiguities*)
scale=2; scale=2;
xtaps=Flatten[{realtaps,Table[0,{(scale-1)taps}]}]; xtaps = Flatten[{realtaps, Table[0, {(scale-1)taps}]}];
(*taps input returns l1=(taps/2)+1 items*) (*taps input returns l1=(taps/2)+1 items*)
complex=Fourier[xtaps,{FourierParameters->{1,1}}]; complex = Fourier[xtaps, {FourierParameters->{1, 1}}];
(*Print[″complex=″,Take[complex,{1,taps*scale,scale}]];*) (*Print[″complex=″, Take[complex, {1, taps*scale, scale}]];*)
len=scale*taps/2; len=scale*taps/2;
l1=len+1; l1=len+1;
ampls=Table[0,{l1}]; ampls = Table[0,{l1}];
delays=Table[0,{l1}]; delays = Table[0,{l1}];
delays[[1]]=dcDelay; delays[[1]] = dcDelay;
ampls[[1]]=Abs[complex[[1]]]; ampls[[1]]=Abs[complex[[1]]];
mod=Pi; mod = Pi;
(*for all non-dc frequencies*) (*for all non-dc frequencies*)
For[i=1,i<=len,++i, For[i=1, i<=len, ++i,
ampl=Abs[complex[[i+1]]]; ampl = Abs[complex[[i+1]]];
ampls[[i+1]]=ampl; ampls[[i+1]]=ampl;
If[ampl<10^-12, If[ampl<10^-12,
(*if amplitude too small for accurate angle,use previous (*if amplitude too small for accurate angle, use previous
delay as this is needed by the delay reconstruction*) delay as this is needed by the delay reconstruction*)
delays[[i+1]]=delays[[i]], Delays[[i+1]]=delays[[i]],
(* else*) (* else*)
(*reconstruct delay using previous delay which should (*reconstruct delay using previous delay which should
work well as long as delay changes,when translated work well as long as delay changes, when translated
to angles,are not>Pi bwtween adjacent frequencies to angles, are not>Pi bwtween adjacent frequencies
at the new frequency*) at the new frequency*)
(*conversion ratio between delays and radians*) (*conversion ratio between delays and radians*)
radiansPerSample=N[Pi*i/len]; radiansPerSample=N[Pi*i/len];
delay=delays[[i]];(*get previous delay*) delay = delays[[i]]; (*get previous delay*)
(*convert previous delay to angle at new frequency*) (*convert previous delay to angle at new frequency*)
prevangle=delay*radiansPerSample; Prevangle=delay*radiansPerSample;
(*get angle at new frequency*) (*get angle at new frequency*)
anale=Mod[Arg[complex[[i+1]]],Pi,prevangle-Pi/2]; anale=Mod[Arg[complex[[i+1]]], Pi, prevangle-Pi/2];
(*Print[″angle=″,angle]:*) (*Print[″angle=″, angle]:*)
newDelay=angle/radiansPerSample; NewDelay = angle/radiansPerSample;
delays[[i+1]]=newDelay; Delays[[i+1]]=newDelay;
]; ];
]; ];
(*where magnitude is too small,angles are unreliable,so (*where magnitude is too small, angles are unreliable, so
average adjacent delays to get delay instead*) Average adjacent delays to get delay instead*)
For[i=1,i<len,++i, For[i=1, i<len, ++i,
If[ampls[[i+1]]<10^-12, If[ampls[[i+1]]<10^-12,
delays[[i+1]]=(delays[[i]]+delays[[i+2]])/2; Delays[[i+1]]=(delays[[i]]+delays[[i+2]])/2;
]; ];
]; ];
If[ampls[[len+1]]<10^-12, If[ampls[[len+1]]<10^-12,
delays[[len+1]]=2 delays[[len]]-delays[[len-1]]; delays[[len+1]]=2 delays[[len]]-delays[[len-1]];
]; ];
Return[{Take[ampls,{1,len+1,scale}], Return[{Take[ampls, {1, len+1, scale}],
Take[delays,{1,len+1,scale}]}]; Take[delays, {1, len+1, scale}]}];
] ]
Page28 Page28
Slavin.txt Slavin.txt
(*in each list,first value is DC,last is at w=Pi=fs/2*) (*in each list, first value is DC, last is at w=Pi=fs/2*)
Taps[ampls_,delays_]:= Taps[ampls_, delays_]:=
Module[ Module[
{l1,l2,len,taps,angles,complex,targetDelay,realtaps}, {l1, l2, len, taps, angles, complex, targetDelay, realtaps},
l1=Length[ampls]; l1=Length[ampls];
l2=Length[delays]; l2=Length[delays];
If[l1!=l2, If[l1! = l2,
Print[″Missmatched amplitude and delay listl lengths.″]; Print[″Missmatched amplitude and delay listl lengths.″];
Abort[]; Abort[];
]; ];
len=l1-1; len=l1-1;
taps=2*len; Taps=2*len;
angles=Table[delays[[i+1]]*i*Pi/len,{i,0,len}]; angles=Table[delays[[i+1]]*i*Pi/len, {i, 0, len}];
(*Print[″angles=″,angles];*) (*Print[″angles=″, angles];*)
complex=PolaroComplex[ampls,angles]; complex = PolaroComplex[ampls, angles];
(*Print[″complex=″,complex];*) (*Print[″complex=″, complex];*)
realtaps=InverseFourier[complex,{FourierParameters->{1,1}}]; realtaps = InverseFourier[complex, {FourierParameters->{1, 1}}];
Return[realtaps]; Return[realtaps];
] ]
(* (*
*Finds symbolic IM and harmonic frequency terms using the frequency *Finds symbolic IM and harmonic frequency terms using the frequency
*index and samples symbols 'ix’and'sx'.’vars’is the list of variables *index and samples symbols 'ix'and'sx'.'vars'is the list of variables
*defining the filter product to use.It is of the form; *defining the filter product to use.It is of the form;
* Flatten[{k,Table[a[j],{j,1,order}],Table[d[j],{j,1,order}]}]; * Flatten[{k, Table[a[j], {j, 1, order}], Table[d[j], {j, 1, order}]}];
*) *)
Terms[ix_,sx_,vars_]:= Terms[ix_,sx_,vars_]:=
Module[ Module[
{r0,r1,r2,r3,r4,r5,t,tt,a,b,c,j,cost,sint,len,i1,i2,p,q,nrVars,order, {r0, r1, r2, r3, r4, r5, t, tt, a, b, c, j, cost, sint, len, i1, i2, p, q, nrVars, order,
q0,q1,q2,q3,q3a,q4,q5,q6,q7,q8,terms,j1,j2,t1,t2}, q0, q1, q2, q3, q3a, q4, q5, q6, q7, q8, terms, j1, j2, t1, t2},
nrVars=Length[vars]; nrVars = Length[vars];
order=(nrVars-1)/2; order=(nrVars-1)/2;
If[!InteggerQ[order], If [! IntegerQ[order],
Print[″Vars list must be of from:″ Print[″Vars list must be of from:″
″{kx,ax0,ax1,...,axn,dx0,dx1,...,dxn}″]; "{kx,ax0,ax1,...,axn,dx0,dx1,...,dxn}"];
Abort[]; Abort[];
]; ];
q0=TrigReduce[(Cos[(ix-1)tt]+Cos[(ix+1)tt])^order]; q0=TrigReduce[(Cos[(ix-1)tt]+Cos[(ix+1)tt])^order];
(*extract tt variable outside as a common factor for each cos term*) (*extract tt variable outside as a common factor for each cos term*)
q1=q0/.Cos[a_]:>Cos[Apart[a]]; q1=q0/.Cos[a_]:>Cos[Apart[a]];
(*expand into seperate terms*) (*expand into separate terms*)
q2=Expand[q1]; q2 = Expand[q1];
(*make into a list*) (*make into a list*)
q3=Table[q2[[j]],{j,1,Length[q2]}]; q3 = Table[q2[[j]], {j, 1, Length[q2]}];
(*eliminate DC frequencies from list*) (*eliminate DC frequencies from list*)
q4=Table[If[NumericQ[q3[[j]]],0,q3[[j]]/(q3[[j]]/.tt->0)], q4=Table[If[NumericQ[q3[[j]]], 0, q3[[j]]/(q3[[j]]/.tt->0)],
{j,1,Length[q3]} {j, 1, Length[q3]}
(*eliminate the Cos[] arount each term*) (*eliminate the Cos[] around each term*)
q5=q4/.Cos[a_]:>Apart[a]; q5=q4/.Cos[a_]:>Apart[a];
(*form(k*ix+m)*tt->k*ix+m for integer k,m*) (*form(k*ix+m)*tt->k*ix+m for integer k, m*)
q6=q5/.a-*tt:>a; q6=q5/.a-*tt:>a;
(*make ix term positive:if k is-ve,then its derivative is-ve*) (*make ix term positive:if k is-ve,then its derivative is-ve*)
q7=Table[If[D[q6[[j]],ix]<0,-q6[[j]],q6[[j]]],{j,1,Length[q6]}]; q7=Table[If[D[q6[[j]],ix]<0,-q6[[j]],q6[[j]]],{j,1,Length[q6]}];
(*eliminate lower-order harmonics from term list*) (*eliminate lower-order harmonics from term list*)
If[order>=2, If[order>=2,
j1=j2=1; j1=j2=1;
(*a higher order contains all the terms in the lower order*) (*a higher order contains all the terms in the lower order*)
t1=Sort[Expand[q7]]; t1=Sort[Expand[q7]];
t2=Sort[AllTerms[ix,order-2]]; t2 = Sort[AllTerms[ix, order-2]];
len1=Length[t1]; len1=Length[t1];
Page29 Page29
Slavin.txt Slavin.txt
len2=Length[t2]; len2=Length[t2];
While[j2<=len1, While[j2<=len1,
If[t1[[j1]]==t2[[j2]], If[t1[[j1]]==t2[[j2]],
t1[[j1]]={}; t1[[j1]]={};
If[j2==len2, If[j2==len2,
Break[]; Break[];
]; ];
j2+=1; j2+=1;
]; ];
j1+=1; j1+=1;
]; ];
terms=Flatten[t1]; terms = Flatten[t1];
, , ,
terms=q7; terms = q7;
]; ];
len=Length[terms]; len=Length[terms];
(*convert into form:Cos[(k*ix+m)*2*Pi*t/sx]*) (*convert into form:Cos[(k*ix+m)*2*Pi*t/sx]*)
cost=terms/.a_:>Cos[Apart[a*2*Pi*t/sx]]; Cost=terms/.a_:>Cos[Apart[a*2*Pi*t/sx]];
(*find corresponding Sin[] terms*) (*find corresponding Sin[] terms*)
sint=cost/.Cos[a_]:>sin[a]; sint=cost/.Cos[a_]:>sin[a];
(*expand general result for order*) (*expand general result for order*)
r0=product[Cos[2*Pi/sx(ix-1)(t-vars[[j+1+order]])]+ r0=product[Cos[2*Pi/sx(ix-1)(t-vars[[j+1+order]])]+
vars[[j+1]]Cos[2*Pi/sx(ix+1)(t-vars[[j+1+order]])], vars[[j+1]]Cos[2*Pi/sx(ix+1)(t-vars[[j+1+order]])],
{j,1,order}]; {j,1,order}];
r1=TrigReduce[r0]; r1=TrigReduce[r0];
r2=r1/.Cos[a_]:>Cos[Collect[Together[a],t]]; r2=r1/.Cos[a_]:>Cos[Collect[Together[a],t]];
r3=r2/.Cos[b_t+c_]->Cos[b*t]*Cos[c]-Sin[b*t]*Sin[c]; r3=r2/.Cos[b_t+c_]->Cos[b*t]*Cos[c]-Sin[b*t]*Sin[c];
r4=r3/.{Cos[a_]:>Cos[Apart[a]],Sin[a_]:>Sin[Apart[a]]}; r4=r3/.{Cos[a_]:>Cos[Apart[a]], Sin[a_]:>Sin[Apart[a]]};
r5=Table[{Coefficient[r4,cost[[j]]],Coefficient[r4,sint[[j]]]}, r5=Table[{Coefficient[r4, cost[[j]]], Coefficient[r4, sint[[j]]]},
{j,1,len}]; {j,1,len}];
Return[{terms,vars[[1]]*r5}]; Return[{terms, vars[[1]]*r5}];
] ]
WfmColor[list_,color_]:= WfmColor[list_, color_]:=
Module[ Module[
{max,r,g,b,data}, {max, r, g, b, data},
r=color[[1]]; r = color[[1]];
g=color[[2]]; g = color[[2]];
b=color[[3]]; b = color[[3]];
data=Transpose[list][[2]]; data = Transpose[list][[2]];
max=Max[data]; max = Max[data];
Return[ListPlot[list,{PlotJoined->True, Return[ListPlot[list, {PlotJoined->True,
GridLines->Automatic, GridLines->Automatic,
PlotRange->{max-150,max+5}, PlotRange->{max-150, max+5},
ImageSize->600, ImageSize->600,
Plotstyle->RGBColor[r,g,b]}]]; Plotstyle->RGBColor[r,g,b]}]];
] ]
EndPackage[] EndPackage[]
Page30 Page30
Claims (4)
Applications Claiming Priority (4)
| Application Number | Priority Date | Filing Date | Title |
|---|---|---|---|
| US62537204P | 2004-11-04 | 2004-11-04 | |
| US60/625372 | 2004-11-04 | ||
| US11/258237 | 2005-10-26 | ||
| US11/258,237 US7161515B2 (en) | 2004-11-04 | 2005-10-26 | Calibration system and method for a linearity corrector using filter products |
Related Child Applications (1)
| Application Number | Title | Priority Date | Filing Date |
|---|---|---|---|
| CN201210049028.5A Division CN102594346B (en) | 2004-11-04 | 2005-11-04 | Calibration system and method for a linearity corrector using filter products |
Publications (2)
| Publication Number | Publication Date |
|---|---|
| CN1790916A CN1790916A (en) | 2006-06-21 |
| CN1790916B true CN1790916B (en) | 2012-05-02 |
Family
ID=36788475
Family Applications (2)
| Application Number | Title | Priority Date | Filing Date |
|---|---|---|---|
| CN 200510131508 Expired - Fee Related CN1815893B (en) | 2004-11-04 | 2005-11-04 | Linearity corrector using filter products |
| CN 200510137332 Expired - Fee Related CN1790916B (en) | 2004-11-04 | 2005-11-04 | Calibration system for a linearity corrector using filter products |
Family Applications Before (1)
| Application Number | Title | Priority Date | Filing Date |
|---|---|---|---|
| CN 200510131508 Expired - Fee Related CN1815893B (en) | 2004-11-04 | 2005-11-04 | Linearity corrector using filter products |
Country Status (1)
| Country | Link |
|---|---|
| CN (2) | CN1815893B (en) |
Families Citing this family (10)
| Publication number | Priority date | Publication date | Assignee | Title |
|---|---|---|---|---|
| JP5609684B2 (en) * | 2011-02-01 | 2014-10-22 | ソニー株式会社 | AD converter and signal processing system |
| JP5733027B2 (en) * | 2011-05-31 | 2015-06-10 | ソニー株式会社 | AD converter and signal processing system |
| CN104991119B (en) * | 2015-07-01 | 2017-10-27 | 天津大学 | A kind of coprime spectral analysis method and its device for eliminating pseudo- peak, composing leakage effect |
| CN105553904B (en) * | 2015-12-09 | 2019-01-15 | 西安星通通信科技有限公司 | A kind of digital signal amplitude and phase calibration method and system |
| CN105680859B (en) * | 2016-01-29 | 2018-09-11 | 中国科学院微电子研究所 | ADC built-in self-test circuit and test method in system on chip |
| KR102642577B1 (en) * | 2016-12-12 | 2024-02-29 | 엘지디스플레이 주식회사 | Driver Integrated Circuit For External Compensation And Display Device Including The Same And Data Calibration Method of The Display Device |
| CN114124037B (en) * | 2020-08-25 | 2025-09-02 | 上海艾为电子技术股份有限公司 | Signal processing device, electronic device, and signal processing method |
| CN114094973B (en) * | 2020-08-25 | 2025-09-02 | 上海艾为电子技术股份有限公司 | Signal processing device, electronic device, and signal processing method |
| WO2022076945A2 (en) * | 2020-10-09 | 2022-04-14 | That Corporation | Genetic-algorithm-based equalization using iir filters |
| CN117155405B (en) * | 2023-08-09 | 2024-07-12 | 海飞科(珠海)信息技术有限公司 | Quick tANS coding and decoding conversion table establishment method based on gradient descent |
Citations (3)
| Publication number | Priority date | Publication date | Assignee | Title |
|---|---|---|---|---|
| US5594612A (en) * | 1994-08-24 | 1997-01-14 | Crystal Semiconductor Corporation | Analog-to-digital converter with digital linearity correction |
| US6384757B1 (en) * | 1999-09-20 | 2002-05-07 | Nokia Networks Oy | Method of calibrating an analog-to-digital converter, and a calibration equipment |
| US6639537B1 (en) * | 2000-03-31 | 2003-10-28 | Massachusetts Institute Of Technology | Highly linear analog-to-digital conversion system and method thereof |
-
2005
- 2005-11-04 CN CN 200510131508 patent/CN1815893B/en not_active Expired - Fee Related
- 2005-11-04 CN CN 200510137332 patent/CN1790916B/en not_active Expired - Fee Related
Patent Citations (3)
| Publication number | Priority date | Publication date | Assignee | Title |
|---|---|---|---|---|
| US5594612A (en) * | 1994-08-24 | 1997-01-14 | Crystal Semiconductor Corporation | Analog-to-digital converter with digital linearity correction |
| US6384757B1 (en) * | 1999-09-20 | 2002-05-07 | Nokia Networks Oy | Method of calibrating an analog-to-digital converter, and a calibration equipment |
| US6639537B1 (en) * | 2000-03-31 | 2003-10-28 | Massachusetts Institute Of Technology | Highly linear analog-to-digital conversion system and method thereof |
Also Published As
| Publication number | Publication date |
|---|---|
| CN1815893B (en) | 2012-04-18 |
| CN1790916A (en) | 2006-06-21 |
| CN1815893A (en) | 2006-08-09 |
Similar Documents
| Publication | Publication Date | Title |
|---|---|---|
| CN101573592B (en) | Compensate for Harmonic Distortion in Instrument Channels | |
| JP4076553B2 (en) | Calibration apparatus and linear corrector calibration method | |
| US20130031442A1 (en) | Multi-Dimensional Error Definition, Error Measurement, Error Analysis, Error Function Generation, Error Information Optimization, and Error Correction for Communications Systems | |
| TWI423589B (en) | Apparatus for and method of generating a sinusoidal signal and method of manufacturing a semiconductor device | |
| US6911925B1 (en) | Linearity compensation by harmonic cancellation | |
| US7348908B2 (en) | Linearity corrector using filter products | |
| CN1790916B (en) | Calibration system for a linearity corrector using filter products | |
| US20080109503A1 (en) | Sine wave generator with dual port look-up table | |
| WO2004030219A1 (en) | System and method for digital compensation of digital to analog and analog to digital converters | |
| Yang et al. | Minimax and WLS designs of digital FIR filters using SOCP for aliasing errors reduction in BI-DAC | |
| Schmidt et al. | Methodology and measurement setup for analog-to-digital converter postcompensation | |
| Mikulik et al. | Volterra filtering for integrating ADC error correction, based on an a priori error model | |
| Kasher et al. | Memory-efficient SFDR-optimized post-correction of analog-to-digital converters via frequency-selective look-up tables | |
| Hu et al. | The digital front end with dual-box digital pre-distortion in all-digital quadrature transmitter | |
| EP1911162A1 (en) | Method of and apparatus for characterising an analog to digital converter | |
| Wang et al. | Multiple Harmonics Fitting Algorithms Applied to Periodic Signals Based on Hilbert‐Huang Transform | |
| Dubois et al. | ADC low-complexity modelling identification and mitigation of baseband intermodulation distortion with instantaneous frequency dependence | |
| Irons et al. | Analog-to-digital converter error diagnosis | |
| Leis | Lock-in amplification based on sigma-delta oversampling | |
| JP2004061415A (en) | Method of testing characteristic of device | |
| CN119291298A (en) | A phase estimation method, signal processing channel and storage medium | |
| Wu et al. | Efficient algorithm for multi-tone spectral test of ADCs without requiring coherent sampling | |
| US7206712B2 (en) | Test apparatus and test method for mixed-signal semiconductor components | |
| CN121049832A (en) | An automatic compensation calibration method for energy meter measurement error | |
| CN119414088A (en) | A phase estimation method, signal processing channel and storage medium |
Legal Events
| Date | Code | Title | Description |
|---|---|---|---|
| C06 | Publication | ||
| PB01 | Publication | ||
| C10 | Entry into substantive examination | ||
| SE01 | Entry into force of request for substantive examination | ||
| C14 | Grant of patent or utility model | ||
| GR01 | Patent grant | ||
| CF01 | Termination of patent right due to non-payment of annual fee |
Granted publication date: 20120502 Termination date: 20191104 |
|
| CF01 | Termination of patent right due to non-payment of annual fee |