markman的笔记 https://bbs.21ic.com/?86789 [收藏] [复制] [RSS]

日志

FIR滤波器基础Part 4

已有 1104 次阅读2005-11-15 19:26 |个人分类:数字滤波器专题|系统分类:网上好文

 Part 4: Implementation
4.1 实现FIR滤波器基本的方法是什么?

  FIR滤波器的结构上包含两个东西:一个是采样点延迟线,一个是系数. 可以由以下方法实现FIR滤波器:
    1. 把输入的采样点放入到延迟线中.
    2. 把延迟线中的数与相应的系数相乘并累加.
    3. 移位, 使下一个输入采样能进入延迟线.

4.2 用C语言如何实现FIR滤波器?

  为了展示众多的方法和技巧,这里提供用C语言实现的FIR滤波器算法。
    * fir_algs_1-0.c : C 源码
    * fir_algs_1-0.zip: C 源码( MS Visual C++ 6.0 工程文件)

  包括以下功能模块:

    1. fir_basic: 实现基本的FIR滤波器
    2. fir_circular: 说明环行buffer是如何实现FIR的。
    3. fir_shuffle: 一些TI的处理器上使用的shuffle down技巧
    4. fir_split: 把FIR滤波器展开为两块,避免使用环行缓存。
    5. fir_double_z: 使用双精度的延迟线,使可以使用一个flat buffer。
    6. fir_double_h: 使用双精度的系数,使可以使用一个flat buffer。

4.3 用汇编如何实现FIR滤波器?

  FIR滤波器的汇编算法是跟处理器对应的,但是大多数普通的系统会使用一个DSP处理器提供的环行缓存。

    1. 配置环行缓存。加载系数和延迟线指针。然后对每个采样点执行以下操作:
    2. Store the incoming data in the delay line; increment the delay-line pointer.
    3. Clear the multiplier-accumulator.
    4. Loop over all coefficients/delays; accumulate the values obtained by multiplying the coefficients by the delayed samples.
    5. Round or truncate the result as the FIR output.

  Alternatively, a "shuffle down" method is used in Texas Instruments' older fixed-point processors to implement circular buffers. The processor literally moves each sample delay values by one slot during each multiply-accumulate (via the "MACD" instruction).

  Each DSP microprocessor manufacturer provides example FIR assembly code in its data books or its application handbooks, so be sure to look at those before you "reinvent the circular buffer".

4.4 如何测试以及实现的FIR滤波器?

  Here are a few methods:

    * Impulse Test: A very simple and effective test is to put an impulse into it (which is just a "1" sample followed by at lest N - 1 zeroes.) You can also put in an "impulse train", with the "1" samples spaced at least N samples apart. If all the coefficients of the filter come out in the proper order, there is a good chance your filter is working correctly. (You might want to test with non-linear phase coefficients so you can see the order they come out.) We recommend you do this test whenever you write a new FIR filter routine.
    * Step Test: Input N or more "1" samples. The output after N samples, should be the sum (DC gain) of the FIR filter.
    * Sine Test: Input a sine wave at one or more frequencies and see if the output sine has the expected amplitude.
    * Swept FM Test: From Eric Jacobsen: "My favorite test after an impulse train is to take two identical instances of the filter under test, use them as I and Q filters and put a complex FM linear sweep through them from DC to Fs/2. You can do an FFT on the result and see the complete frequency response of the filter, make sure the phase is nice and continuous everywhere, and match the response to what you'd expect from the coefficient set, the precision, etc."

4.5 在实现FIR滤波器的过程中有什么有用的技巧?

  FIR tricks center on two things 1) not calculating things that don't need to be calculated, and 2) "faking" circular buffers in software.

4.5.1 如何跳过不必要的计算?

  First, if your filter has zero-valued coefficients, you don't actually have to calculate those taps; you can leave them out. A common case of this is "half-band" filter, which have the property that every-other coefficient is zero.

  Second, if your filter is "symmetric" (linear phase), you can "pre-add" the samples which will be multiplied by the same coefficient value, prior to doing the multiply. Since this technique essentially trades an add for a multiply, it isn't really useful in DSP microprocessors which can do a multiply in a single instruction cycle. However, it is useful in ASIC implementations (in which addition is usually much less expensive than multiplication); also, some newer DSP processors now offer special hardware and instructions to make use of this trick.

4.5.2 How do I fake circular buffers in software?

  When hardware support for circular buffers isn't available, you have to "fake" them. Also, since ANSI C has no construct to describe circular buffers, most C compilers can't generate code to use them, even if the target processor has them.

  You can always implement a circular buffer by duplicating the logic of a circular buffer in software (and many have), but the overhead can be prohibitive; the circular-fake might take several instructions to implement, compared to just a single instruction to do the multiply-accumulate operation. Therefore you need to fake it.

  Here are several basic techniques to fake circular buffers:

    1. Split the calculation: You can split any FIR calculation into its "pre-wrap" and "post-wrap" parts. By splitting the calculation into these two parts, you essentially can do the circular logic only once, rather than once per tap. (See fir_double_z in FirAlgs.c above.)
    2. Duplicate the delay line: For a FIR with N taps, use a delay line of size 2N. Copy each sample to its proper location, as well as at location-plus-N. Therefore, the FIR calculation's MAC loop can be done on a flat buffer of N points, starting anywhere within the first set of N points. The second set of N delayed samples provides the "wrap around" comparable to a true circular buffer. (See fir_double_z in FirAlgs.c above.)
    3. Duplicate the coefficients: This is similar to the above, except that the duplication occurs in terms of the coefficients, not the delay line. Compared to the previous method, this has a calculation advantage of not having to store each incoming sample twice, and it also has a memory advantage when the same coefficient set will be used on multiple delay lines. (See fir_double_h in FirAlgs.c above.)
    4. Use block processing: In block processing, you use a delay line which is a multiple of the number of taps. You therefore only have to move the data once per block to implement the delay-line mechanism. When the block size becomes "large", the overhead of a moving the delay line once per block becomes negligible.

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)