\n", "\n", "

" ] }, { "cell_type": "markdown", "id": "dd6ccfdb-12f6-42b3-9504-caea3826cc73", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "## FIR filter design\n", "\n", "For typical frequency selective filters, the design goals are threefold\n", "\n", "* Minimize distortion of the signal in the passband(s)\n", "* Attenuate the stopband as much as possible\n", "* Keep the order of the filter low" ] }, { "cell_type": "markdown", "id": "2fbdfcde-7a3d-4531-be1e-220dc04729be", "metadata": { "tags": [ "remove-nb-cell" ] }, "source": [ "As an example, consider the design of a bandpass filter. Ideally, the passband would have a gain of 0 dB and the two stopbands would have a gain of $-\\infty$ dB. However, we know that such an ideal filter would require infinite delay. In practice, we tolerate some amount of distortion in the passband and accept a small amount of leakage through the stopband. This leads to two important design tradeoffs:\n", "\n", "* Better frequency selectivity vs lower delay\n", "* Performance in the passband(s) vs performance in the stopband(s)" ] }, { "cell_type": "markdown", "id": "beabd09b-9a6b-414f-9015-6aef9e2d8477", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [ "remove-nb-cell" ] }, "source": [ "![](../img/bandpass.svg)" ] }, { "cell_type": "markdown", "id": "a3b745ec-b537-4918-baad-ca4f5392dfee", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [ "remove-cell" ] }, "source": [ "\n", "\n", "

" ] }, { "cell_type": "markdown", "id": "b9c462fc-ccdc-47a1-b5e6-f489418f5c4d", "metadata": { "tags": [ "remove-nb-cell" ] }, "source": [ "The [Parks-McClellan algorithm](https://en.wikipedia.org/wiki/Parksâ€“McClellan_filter_design_algorithm) (aka equiripple) produces a set of filter coefficients that is optimal in the sense that it minimizes the worst deviation between the actual response and the desired response. When using this method, we have control over several parameters:" ] }, { "cell_type": "markdown", "id": "9a601d5f-acc4-4a65-aec7-63972b4921a0", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "* Filter order $N$\n", " * Lower order will provide shorter delay\n", " * Higher order will provide better frequency selectivity\n", "* Relative weights $W$\n", " * Specifies how to weight each passband and stopband when computing the error that is minimized by the algorithm\n", "* Location of transition regions (specified by $f_{\\text{pass}_i}$ and $f_{\\text{stop}_i}$)\n", " * Transition regions cause to much distortion to function as a passband but not enough attenuation to function as a stopband\n", " * Smaller transition region increases the amount of usable bandwidth\n", " * Larger transition region will provide better performance in the passband and stopband" ] }, { "cell_type": "markdown", "id": "0057072e-619e-4da2-9395-c9d59ce19bfd", "metadata": { "tags": [ "remove-nb-cell" ] }, "source": [ "Other FIR filter design methods include [least-squares](https://en.wikipedia.org/wiki/Filter_design#Methodology) and [window design methods](https://en.wikipedia.org/wiki/Finite_impulse_response#Window_design_method)." ] }, { "cell_type": "markdown", "id": "8e78abbb-2b82-4d8e-9362-a1167aea6937", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [ "remove-cell" ] }, "source": [ "# Week 2" ] }, { "cell_type": "markdown", "id": "5eff9238-b9c4-4cfe-a5d2-597fec30cea4", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "## Frame-based processing" ] }, { "cell_type": "markdown", "id": "ff71f990-2711-4fce-8325-159a5667b754", "metadata": { "tags": [ "remove-nb-cell" ] }, "source": [ "For a real-time system, data is constantly flowing in from the ADC and out to the DAC. We can configure how many samples to collect between interrupt triggers from the ADC.\n", "\n", "In the extreme case, we can trigger an interrupt each time a new sample is available and immediately compute one output sample of the filter. alternatively, we can wait until a frame of $N_F$ samples is collected before triggering an interrupt then compute $N_F$ output samples of the filter.\n", "\n", "There are a number of advantages to a frame-based implementation:" ] }, { "cell_type": "markdown", "id": "51ec3f2d-1d6f-4126-9b01-9f86bb0c3457", "metadata": {}, "source": [ "* Less overhead\n", " * Each interrupt requires a fixed number of processor cycles $N_I$.\n", " * For sample-by-sample processing, this cost is incurred for each sample\n", " * For frame-based processing, this is reduced to $N_I / N_F$ per sample\n", "* Computational advantages\n", " * Algorithms to filter $N_f$ samples can be more efficient than algorithms that operate sample-by-sample\n", " * Allows use of single instruction multiple data (SIMD) operations\n", "* Memory advantages\n", " * In some systems, large blocks of memory can be moved more efficiently.\n", " * Caching may be more efficient with large frames" ] }, { "cell_type": "markdown", "id": "fe84b6b7-64d0-40c4-8422-3083931c9822", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [ "remove-cell" ] }, "source": [ "# Week 3" ] }, { "cell_type": "markdown", "id": "1410f22c-5383-4e42-baaf-d2808247cd52", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "## IIR Filters\n", "\n", "For a causal discrete-time IIR filter, each output sample $y[n]$ is computed from a set of feedforward terms and a set of feedback terms.\n", "\n", "$$ y[n] = \\underbrace{\\sum_{k=0}^{N}{b_k x[n-k]}}_{\\text{feedforward}}-\\underbrace{\\sum_{k=1}^{N}{a_k y[n-k]}}_{\\text{feedback}} $$\n", "\n", "The choice to subtract the feedback terms rather than add them is arbitrary, but this is conventional because it leads to a slightly simpler expression of the transfer function in the z-domain\n", "\n", "$$ H(z) = \\frac{b_0 + b_1 z^{-1} + \\cdots + b_N z^{-N}}{1 + a_1 z^{-1} + \\cdots + a_N z^{-N}} $$" ] }, { "cell_type": "markdown", "id": "6304da74-9c16-4b22-9637-f9c134d9f577", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [ "remove-nb-cell" ] }, "source": [ "![](../img/iir_df_I.svg)" ] }, { "cell_type": "markdown", "id": "f9099189-c59e-44ff-87c4-7c97eb8b4cce", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [ "remove-cell" ] }, "source": [ "\n", "\n", "

" ] }, { "cell_type": "markdown", "id": "e5e08717-c21d-4d4a-90dc-eaa49116ce09", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "## Numerical errors\n", "With finite precision data types, many sequences of operations can be carried out with perfect accuracy. For example:\n", "\n", "```matlab\n", ">> single(7.2)*single(13.8)*single(1.0)\n", "\n", " 99.36\n", "```\n", "\n", "In general however, operations using finite precision data types (such as single precision floating point) are subject to numerical errors. For example:\n", "\n", "```matlab\n", ">> single(7.2)*single(13.8e-35)*single(1.0e35)\n", "\n", " 99.35999\n", "```\n", "\n", "These numerical errors can cause serious issues in the design and implementation of IIR filters." ] }, { "cell_type": "markdown", "id": "52b21a8e-dae1-468e-9a82-43e61c270cf3", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "## Cascade of biquads\n", "\n", "Previously, the transfer function was expressed in terms of the coefficients $b_k$ and $a_k$. Alternatively, we can express it in terms of poles $p_k$, zeros $\\zeta_k$, and a constant gain $C$.\n", "\n", "$$ H(z) = C \\frac{(z-\\zeta_1)(z-\\zeta_2)\\cdots(z-\\zeta_N)}{(z-p_1)(z-p_2)\\cdots(z-p_N)} $$\n", "\n", "A downside of this representation is that, even if all $a_k$ and $b_k$ are real, the corresponding $p_k$ and $\\zeta_k$ may be complex. Alternatively, we can group together pairs of conjugate symmetric poles and zeros to create a similar similar representation where all of the coefficients are real. This is known as a cascade of biquads or a second-order sections representation.\n", "\n", "$$ H_k(z) = \\frac{b_{k,0} + b_{k,1} z^{-1} + b_{k,2} z^{-2}}{1 + a_{k,1} z^{-1} + a_{k,2} z^{-2}} $$\n", "\n", "$$ H(z) = H_1(z)H_2(z) \\cdots H_M (z) $$\n" ] }, { "cell_type": "markdown", "id": "f87a5630-b5f0-45c3-a722-178b9d5eb140", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [ "remove-nb-cell" ] }, "source": [ "![](../img/cascade_biquads.svg)" ] }, { "cell_type": "markdown", "id": "d6be3b4d-52b3-4b4e-ae11-ccc634b9b519", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [ "remove-cell" ] }, "source": [ "\n", "\n", "

" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.2" } }, "nbformat": 4, "nbformat_minor": 5 }