.. ECE 4703 .. _lab 2: Lab 2: Implementation of FIR filters ==================================== The purpose of this assignment is as follows. * to familiarize you with the filter design tools in Matlab, * to familiarize you with the basic calibration of signal values captured using AUDIO BOOSTXL, * to familiarize you with the implementation of finite impulse reponse (FIR) filtering using MSP-EXP432P401R, * to compare the performance of various FIR implementation styles. Finite Impulse Response Filter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ An FIR filter with M taps is a digital filter described by the following input/output relationship .. math:: y[n] = \sum_{k=0}^{M-1} b[k] x[n-k] where :math:`y[n]` is the current filter output, :math:`b[0],...,b[M-1]` are the feedforward filter coefficients, and :math:`x[n],...,x[n-M+1]` are the current input and :math:`M-1` previous inputs. The inputs are stored in a buffer referred to as the *taps* of the FIR filter. To compute the very first filter output :math:`y[0]` using the very first input :math:`x[0]`, one must assume an initial value for :math:`x[-1],...,x[-M+1]`. In this lab we will assume that the initial value of the taps of the FIR filter is 0. This lab is focused on the implemention of the formula to compute an FIR output using a DSP program in C. We are primarily concerned with the correct implementation of the FIR design using floating-point precision. In a later assignment, we will study the optimized implementation of the FIR design using fixed-point arithmetic. Finite Impulse Response Filter Specifications ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In this lab you will develop an implementation for an FIR filter with the following specifications. You will design a lowpass filter with a cutoff of 1336 Hz and a stopband starting at 1477 Hz. The maximum passband rippple is 1dB, and the required stopband rejection is 40 dB. You may recognize that the frequencies 1336 Hz and 1477 Hz are not arbitrarily chosen. These frequencies correspond to two DTMF column frequencies. The filter will pass DTMF keys from the left two columns, but will remove the column frequency of any key tone from the right two columns. You can pick any supported sample rate and any filter design method you like, as long as your design meets all of the filter design requirements including real-time performance. You can use Matlab filter design tools such as ``filterDesigner`` to create the coefficients for your FIR filter. The Matlab filter design tools allow you to analyze various aspects of your filter such as its impulse response, frequency response, and pole-zero plot, among others. The Matlab filter design tools allow you to export the filter coefficients as a C header file. You can use these generated coefficients directly in your program. You will perform all calculations in this assignment using single-precision floating point numbers. .. note:: C recognizes multiple floating-point precision levels, and the most common ones are single-precision floating point (``float``) and double-precision floating point (``double``). Single-precision floating point is a 32-bit datatype (a sign bit, 8 exponent bits and 23 mantissa bits), while double-precision floating point commonly uses 64 bits. A floating-point constant can be written in various ways. For example, the value 0.75 can be written as ``0.75`` or ``75e-2`` or ``.0075e2``. Without a floating-point suffix, such a constant is treated as having double precision. The floating-point suffix ``f`` can be added to indicate the compiler that you are providing a single-precision floating constant. Thus, the value 0.75 as a single-precision constant can be written as ``0.75f`` or ``75e-2f``. In ``filterDesigner``, coefficients can be generated as single-precision floating point, double-precision floating point, and even fixed-point. The single-precision floating point data type used by ``filterDesigner`` is ``real32_T``, while the same data type in our program (and in the ARM CMSIS standard) is called ``float32_t``. You'll have to make sure to add a definition that equates the two data types, or modify the C file generated by Matlab. Keep in mind that the number of filter coefficients that can be processed in real time on your board are limited. As a rule of thumb, any number of taps above 50 will require you to turn on compiler optimization (left-click on project to reveal Project Properties, then select 'Optimization'). If you implement a filter that is a too heavy load for the board, you will notice that the real time performance of the program is not longer achieved. Most obviously, the DTMF generator (which will run alongside your filter code) will no longer generate correct row- and column frequencies. Calibration ^^^^^^^^^^^ Before you will develop your real-time DSP filter, you first have to gain insight into the calibration of analog signals into digital floating point numbers. The MSP-EXP432P401R Launchpad used for your course project contains a 14-bit Analog to Digital Converter, which converts analog voltages between 0 volts and 3.3 volts (full scale). The processed signal from the MSP432 processor is converted through digital audio using a 14-bit Digital to Analog Converter integrated on the `Audio Signal Processing Boosterpack `_. The DAC converts digital codes to analog voltages between 0 volts and 3.3 volts (full scale). The following figure illustrates the calibration of analog values to digital numbers. The ADC produces 14-bit numbers which are mapped into a 16-bit unsigned data type. These integers are converted into single-precision floating-point numbers using ``float32_t xlaudio_adc14_to_f32(uint16_t)``, a function provided in :ref:`xlaudio_lib`. The lowest ADC value (0) is mapped to the real value -0.25, and the highest ADC value (0x3FFF) is mapped to the real value 0.25. A floating point number can be converted back to a voltage by first converting the number to a 16-bit unsigned integer using ``uint16_t xlaudio_f32_to_dac14(float32_t)``, and next sending that number to the 14-bit DAC. .. figure:: images/lab2_calibration.png :figwidth: 500px :align: center Calibration Chart relating analog values, DAC/ADC values, and floating point values We recall how a typical real-time DSP program looks like. We demonstrate the case of an interrupt-driven sample conversion with a 8 KHz sample rate. .. code:: c :number-lines: 1 #include "xlaudio.h" uint16_t processSample(uint16_t x) { float32_t v = adc_to_f32(x); // ... DSP code goes here return f32_to_dac(v); } int main(void) { WDT_A_hold(WDT_A_BASE); xlaudio_init_intr(FS_8000_HZ, XLAUDIO_J1_2_IN, processSample); xlaudio_run(); return 1; } .. important:: **Question 1**: Create a DTMF signal for any of the 16 keys of the DTMF keypad. * Your DTMF key code must be programmed through the LEFT button of the board. Pressing the left button will increase the DTMF code (modulo 16). Do NOT make use of the RIGHT button; we will assign the RIGHT button a different functionality in a later part of the lab. * Your DTMF waveform must be calibrated such that the DTMF signal measures 2.4V peak-to-peak. You may make use of the ``dtmf_generator`` code discussed in the first week of class. You can make use of the :ref:`xlaudio_lib` functions, for example to read the state of the buttons. In your answer, include a screen shot of a DTMF waveform (both sines included), a screen shot of the row-sine by itself, and a screenshot of the column-sine by itself. Demonstrate that the signal has the required amplitude. .. note:: The Digilent WaveForms software allows you to measure the peak-to-peak amplitude of a waveform using the 'Measurements' menu. You will see that different DTMF codes may yield a slightly different peak-to-peak value. Choose your scaling factor such that at least one DTMF frequency has a peak-to-peak amplitude of 2.4 Volt. Filter Coefficient Generation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the Matlab ``filterDesigner`` tool to create a FIR according to the passband specifications provided earlier. You can choose any suitable sample frequency as long as it yields a filter that meets the passband specifications. .. important:: **Question 2**: Generate floating point coefficients that can be included in a C file. When your design is complete, extract the following information from ``filterDesigner``: the filter's impulse response, the filter's amplitude response, the filter's phase response, and the filter's pole-zero plot. You will include these plots in your report. Filter Implementation: FIR Direct Form ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Implement a Direct-Form FIR filter using the coefficients created earlier. The first implementation is the so-called Direct Form implementation, illustrated in the figure below. You will have to adjust the number of taps of the filter to the number identified by the Matlab filter design program. Call this function ``processSampleDirect``. .. figure:: images/lab2_fir_direct.png :figwidth: 300px :align: center Direct Form FIR filter To test the filter, integrate your code for question 1 into the FIR filter, such that the input for the FIR filter is taken from your DTMF generator. Essentially, the DAC code that is sent to the DAC in the program of question 1, will be used as the ADC input code for ``processSampleDirect``. You can integrate the DTMF signal generation the FIR filter directly in software (i.e., ``processSampleDirect`` handles DTMF signal generation as well as FIR filtering). .. important:: The following configuration of the pushbuttons will make testing easy. * When no button is pressed, a DTMF signal containing both row and column frequency are fed into the filter, and the filter output is send to the speaker. * When the right button is pressed, the DTMF signal containing both row and column frequency is directly fed to the speaker, without filtering. .. note:: Getting a complex filter operation to work 'out of the box' is challenging, so if the filter does not work as described above, don't despair. You can work systematically through the design to make sure that everything works as expected. Here are some tips. First, the MSP432EXP401R does not have a straightforward error reporting. One of the first, basic tests that you can do, is to verify that the program is running. The ``DAC_SYNC``, which toggles once for every two bytes transmitted to the DAC, enables you to verify that there is digital data moving from the MSP432EXP401R microcontroller to the DAC on the Audio BoostXL board. To measure this signal, connect an oscilloscope probe to pin ``D sync`` on header J2 of the Audio BoostXL board. If you don't observe a DAC sync pulse, but you believe that there should be one, then the MSP432EXP401R may have suffered an exception -- which halts execution of the DSP program. Such an exception typically occurs when you have an out-of-bounds array access. Second, if the program is running, but you don't get any output, you may need to observe the signal being send to the audio amplifier. Refer to :ref:`connect_scope` to check where you need to connect the oscilloscope probe. Once the oscilloscope is connected you can perform simple tests - such as applying 0v or 3V3 to the input pin ``XLAUDIO_J1_2_IN``, and verifying that the output level of the DAC reacts correspondingly. Work systematically through the signal processing chain from the input to the output. Verify your work frequently and make small modifications at a time. Finally, you can rely on the source-level debugger included in Code Composer Studio. However, since the source-level debugger essentially halts the real-time behavior of the program (masking further interrupts etc), this debugging technique is not very helpful to identify issues related to the real-time nature of the processing. .. figure:: images/lab2_dacsync.png :figwidth: 600px :align: center DAC SYNC of an audio stream at 16KHz sample rate .. attention:: Make sure that the sample rate of the output signal (as measured through the DAC SYNC) is the same as the sample frequency you will choose for your filter. If your filter is too slow, optimize the C code. You can also enable the compiler optimization (under Project Properties -> CCS Build -> Arm Compiler -> Optimization) Measuring the performance of the FIR filter """"""""""""""""""""""""""""""""""""""""""" The performance of the FIR filter is the amount of clock cycles required to process a single signal sample. The total amount of clock cycles available to process a sample equals ``48 MHz / sample frequency``. For example, at 16KHz there are 3000 clock cycles available for each sample. Hence, it is important to understand how much computation effort is needed to process one sample. The :ref:`xlaudio_lib` has a built-in function to compute the performance for you: ``uint32_t xlaudio_measurePerfSample(msp432_sample_process_t _cb)``. Study the source code of this function to understand how it works. You would typically call ``xlaudio_measurePerfSample`` during the initialization phase of the program, before you start the signal processing loop. The return of this function is the number of clock cycles needed to complete the function. You can ``printf`` this number and read it from the console in the debugger of Code Composer Studio. .. important:: **Question 3**: Write the C function that computes the FIR using Direct Form. You have to report the following data for this function: 1. The source code listing of ``uint16_t processSampleDirect(uint16_t x)`` 2. The performance of the implementation 3. The amplitude response of the FIR filter expressed as two screen shots showing the response of the FIR filter to (a) a DTMF signal with a column frequency in the cutoff band, i.e. from the rightmost columns and (b) a DTMF signal with a column frequency in the pass band, i.e. from the leftmost columns. Filter Implementation: Optimizing the FIR Direct Form ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Closely study the filter coefficients. Optimize your filter design for performance by exploiting the symmetry available in the filter coefficients. Once you made the necessary modifications, repeat the same measurements as above: measure the frequency spectrum of the filter, and the performance of the filter. .. important:: **Question 4**: Write the C function that optimizes the FIR direct form. You have to report the following data for this function: 1. The source code listing of ``uint16_t processSampleDirectOptimized(uint16_t x)`` 2. The performance of the implementation 3. The amplitude response of the FIR filter expressed as two screen shots showing the response of the FIR filter to (a) a DTMF signal with a column frequency in the cutoff band, i.e. from the rightmost columns and (b) a DTMF signal with a column frequency in the pass band, i.e. from the leftmost columns. Filter Implementation: The FIR Transpose Form ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following transformation of the filter is called the Transpose Form. It is functionally identical to the Direct Form (with the same coefficients), but it stores intermediate results in the filter taps, rather then the previous input values. .. figure:: images/lab2_fir_transpose.png :figwidth: 300px :align: center Transpose Form FIR Implement this filter and perform the same measurements as you did for the other two filters. .. important:: **Question 5**: Write the C function that optimizes the FIR transpose form. You have to report the following data for this function: 1. The source code listing of ``uint16_t processSampleTranspose(uint16_t x)`` 2. The performance of the implementation 3. The amplitude response of the FIR filter expressed as two screen shots showing the response of the FIR filter to (a) a DTMF signal with a column frequency in the cutoff band, i.e. from the rightmost columns and (b) a DTMF signal with a column frequency in the pass band, i.e. from the leftmost columns. Wrapping Up ^^^^^^^^^^^ * The answer to this lab consists of a written report which will be submitted on Canvas by the deadline. Refer to the General Lab Report Guidelines for details on report formatting. You will only submit your written report on Canvas. All code developed must be returned through github. * Not everybody in the class may be using the same setup to make oscilloscope measurements. Start your report with a short introduction on your measurement setup including the MSP-EXP432P401R kit, the oscilloscope and the signal generator that you have used for this lab. * Follow the five questions outlined above to structure your report. Optionally answer the bonus question. Use figures, screenshots and code examples where appropriate. Please work out the answers in sufficient detail to show your *analysis*. * Make sure that you add newly developed projects to your github repository. Further, make sure that you commit and push all changes to the github repository on GitHub classroom. Use the Team - Commit pop-up menu and push all changes. * Be aware that each of the laboratory assignments in ECE4703 will require a significant investment in time and preparation if you expect to have a working system by the assignment’s due date. This course is run in “open lab” mode where it is not expected that you will be able to complete the laboratory in the scheduled official lab time. It is in your best interest to plan ahead so that you can use the TA and instructor’s office hours most efficiently. *Good Luck* Grading Rubric ^^^^^^^^^^^^^^ +---------------------------------------------------------+------------+ | Requirement | Points | +=========================================================+============+ | Question 1 Analysis | 15 | +---------------------------------------------------------+------------+ | Question 2 Analysis | 15 | +---------------------------------------------------------+------------+ | Question 3 Analysis | 15 | +---------------------------------------------------------+------------+ | Question 4 Analysis | 15 | +---------------------------------------------------------+------------+ | Question 5 Analysis | 15 | +---------------------------------------------------------+------------+ | All projects build without errors or warnings | 5 | +---------------------------------------------------------+------------+ | Code is well structured and commented | 5 | +---------------------------------------------------------+------------+ | Git Repository is complete and up to date | 5 | +---------------------------------------------------------+------------+ | Overall Report Quality (Format, Outline, Grammar) | 10 | +---------------------------------------------------------+------------+ | **TOTAL** | **100** | +---------------------------------------------------------+------------+