.. _lab 6: Lab 6: BPSK Demodulator ======================= The purpose of this assignment is as follows. * to implement a transmitter-receiver chain for BSPK modulated data transmission * to study and implement an algorithm for symbol timing recovery .. attention:: You cannot solve the lab if you have only a single board. In case you work in a team of one, please seek a partner for this lab and share your board. In exceptional cases the instructor can loan you an extra MSP432 + AUDIOXL board. However, since this lab has considerable complexity, it is to your advantage to work as a team. BPSK Demodulator ---------------- In this lab, you will combine a BPSK modulator with a BPSK demodulator. The transmission will be done in baseband; that is, the pulse-shaped symbols will be directly transmitted over a wire from a transmitter board to a receiver board. The following figure shows how to configure the setup for the lab. You'll be using two MSP432 boards. You need a single flywire connected from the DAC output of the board designated 'transmitter' to the ADC input of the board designated 'receiver.' Each board has to be properly grounded using the ground connections (black wires) of the Analog Discovery II scope. Channel 1 of the scope (orange wire) will be used to observe the DAC output of either the transmitter or else the receiver—depending on the question. Channel 2 of the scope (blue wire) will be used to observe the debug pin (J3.5) of either the transmitter or else the receiver. Again, this depends on the question. .. figure:: images/lab6setup.png :figwidth: 600px :align: center After you have constructed the setup, check out the lab 6 repository into CCS. You should find the following projects: - **lab6_q1_bpsk_rxdefault**: Receiver for Question 1 without symbol timing recovery. - **lab6_q1_tx**: Transmitter for Question 1, 2, 3 and 4. - **lab6_q2_bpsk_rx_zcted**: Receiver for Question 2 (Zero-Crossing Timing Error Detector) - **lab6_q3_bpsk_rx_interpolator**: Receiver for Question 3 (Symbol Interpolation) - **lab6_q4_bpsk_rx_zcted_loop**: Receiver for Question 4 (Symbol Timing Synchronizer) Symbol Timing Synchronization ----------------------------- he objective of symbol timing synchronization is simple. At the transmitter, symbols are digitally pulse-shaped with a root-raised-cosine shape and forwarded to the receiver. The receiver filters the signal with a matching root-raised-cosine shape to obtain a signal with a raised-cosine shape. The objective of symbol timing synchronization is to determine when the received raised-cosine shape should be sampled to recover the transmitted symbols. Previously, you plotted the received signal in an eye diagram, which offers a visual mechanism to determine symbol timing. However, to do this automatically, we have to understand the concept of symbol timing error more precisely. Two aspects play a role: the fractional delay caused by the transmission (symbol timing offset), and the difference between the transmitter and receiver clock (symbol timing drift). 1. **Symbol Timing Offset**: The most open position of the eye diagram does not have to coincide with a particular sample. In the lecture on the Costas Loop, one example was given that by changing the carrier phase by 90 degrees, the demodulated signal experiences a fractional shift (i.e., a time shift of less than a sample), so that the optimal sample position of the eye diagram fell in between two samples. Removing the effect of a fractional delay requires interpolation in the sample stream to reconstruct the sample value at the ideal position. The following shows an eye diagram. The blue sample grid (drawn at two samples per symbol period) shows the ideal alignment, as there is one blue sample precisely aligned with the eye. When a timing error exists, however, it is possible to end up with the red sample grid (drawn at the same two samples per symbol). The red samples are either too early or too late to sample the optimal eye. The solution is to estimate (interpolate) the ideal blue sample using the red samples. .. figure:: images/lab6-fracdelay.png :figwidth: 400px :align: center 2. **Symbol Timing Drift:** The receiver and transmitter clocks are implicitly assumed to be identical, but for a real implementation, you will see that this assumption is incorrect. The effect of a difference in receiver and transmitter clock—no matter how small—is that the sample rate used by the transmitter and the receiver is slightly different. This has important consequences on symbol timing since DSP systems express each symbol as an integral number of samples. Hence, when the receiver and transmitter clocks are different, there will be a slow drift where either the symbols at the receiver side appear to come too fast (when the tx clock is faster than the rx clock) or the symbols at the receiver side appear to come too slow (when the tx clock is slower than the rx clock). The following figure shows an exaggerated case of a slow receiver clock, which causes symbol timing errors and eventually even missing symbols. .. figure:: images/lab6-symfreqerr.png :figwidth: 600px :align: center In this lab, we wille explore and solve these two problems. The overall outline of the lab is as follows. - In question 1, you will investigate the effect of symbol frequency errors by connecting a transmitted and a receiver without any symbol timing correction - In question 2, you will study a symbol timing error detector, an algorithm that can tell you how close the symbol samples of the receiver align with the most open eye diagram position. - In question 3, you will study the use of an interpolator algorithm to reconstruct optimal symbol samples from the set of received symbol samples. - In question 4, you will combine the result of questions 2 and 3 to create a symbol timing error correction loop. The result of question 4 is a fully operation based BSPK transmitter-receiver chain. In this lab, you can ignore channel distortion and equalization. Part 1: The impact of clock frequency on Symbol Timing ------------------------------------------------------ Configure your design as follows. One board acts as a BPSK transmitter and runs ``lab6_q1_tx``. The second board acts as a BPSK receiver and runs ``lab6_q1_bpsk_rxdefault``. Study the programs and determine the major modulation parameters (samples per symbol, number of symbols in the shaping filter, rolloff factor in the shaping filter). **Step 1** Run both programs at the same time. Observe the receiver output (Channel 1) and use the debug pin of the transmitter as a trigger on Channel 2. The debug pin contains the symbol sync pulse and is asserted once per transmitted symbol. Demonstrate that you can capture an eye diagram similar to the one shown below. This confirms that the transmitter/receiver chain is working properly. .. figure:: images/lab6q1example.png :figwidth: 600px :align: center **Step 2** Move the Channel 2 connection to the debug pin of the receiver. The receiver debug pin contains the symbol sync pulse used by the receiver. Is the eye diagram still visible? If needed, refresh the persistence plot several times. Well, it looks like you cannot reconstruct the proper symbols at the receiver using only receiver timing signals. What is the cause of this behavior? Find a plausible explanation and summarize it in your report. **Step 3** Make a direct comparison of the transmitter symbol sync and the receiver symbol sync by using Channel 2 (Blue) for the transmitter sync and Channel 1 (Orange) for the receiver sync. You don't need to create a persistence plot but rather observe directly on the timing waveform display. The display should look similar to the one below. Your task is to determine, as accurately as possible, the frequency difference between the transmitter symbol rate and the receiver symbol rate. .. figure:: images/lab6q1ex2.png :figwidth: 600px :align: center **Step 4** The difference between the symbol rate at the transmitter and receiver is significant, and this is because the board uses an internal RC oscillator by default. Such a design allows the chip to work completely stand-alone, but the RC oscillator design is subject to considerable manufacturing variations. Hence, you may find that the receiver is either faster or else slower than the transmitter, and you may find the difference is substantial. You can improve the mismatch somewhat by using the external crystal present on the transmitter and receiver board. Indeed, a typical crystal has a deviation of a few ppm, which will result in a much better match between the transmitter symbol rate and receiver symbol rate. To use the crystal, add the following line of code just before ``xlaudio_init_intr(..)``: .. code:: xlaudio_clocksystem(XLAUDIO_XTAL); Observe the impact on the transmitter and receiver symbol sync pulses. Your task is to determine, again as accurately as possible, the frequency difference between the transmitter symbol rate and the receiver symbol rate. It may look like the rates are identical, but you will very likely still see one symbol sync creep forward or backward with respect to the other. .. attention:: The xlaudio_clocksystem function call requires you to update your ``xlaudio_lib`` library. Go to the project, select Team->Pull to get the latest version from GitHub. Recompile the library, before you recompile the transmitter and the receiver. If you successfully complete this part, you will find that the transmitter and receiver symbol rates are very close when both run from a crystal clock source. Under this condition, we can consider the symbol timing drift almost negligible. In the remainder of the questions, make sure that you always use ``xlaudio_clocksystem(XLAUDIO_XTAL)``. .. important:: **Question 1:** Summarize your findings of the experiments in part 1. Add eye diagrams for Step 1 and Step 2, and describe how you found the frequency difference between transmitter and receiver symbols for Step 3 and Step 4. Part 2: Symbol Timing Error Estimation -------------------------------------- The symbol timing error is the distance between the position where a receiver samples the symbol value and the position where the receiver can sample the optimal symbol value (i.e., where the eye is most open). There are several algorithms available to help determine the timing error, and we will discuss a well-known algorithm called the Zero-Crossing Timing Error Detector. The idea of this error detector, due to Floyd Gardner, is that the receiver signal must cross zero when symbols of opposite sign are transmitted. To understand how the zero crossings are used, consider the following sequence of a +1 symbol followed by a -1 symbol. If the symbol timing is correct, then the zero-crossing point should lie exactly halfway between the two symbol boundaries. Hence, this midpoint value indicates how good the symmetry is between the left and right symbol side. Now, suppose that the symbol timing sync of the receiver runs late, meaning that the symbol peak has already passed when we sample it (red curve). In this case, the midpoint value becomes negative. Conversely, if the symbol timing sync of the receiver runs early, meaning we sample before the symbol peak (purple curve), then the midpoint value becomes positive. .. figure:: images/lab6-q2-zc.png :figwidth: 600px :align: center This leads to a nice and compact expression to describe the symbol timing error. It requires two adjacent symbol values, symbol N and symbol N+1, and the midpoint signal value. The symbol values are +1 or -1, while the midpoint value is a floating-point value. This error expression automatically corrects for the sign of the symbol transition. Indeed, if symbol N is negative (-1) and symbol N+1 is positive (+1), then the midpoint value is negative for late timing and positive for early timing. .. code:: error = midpoint_value * (symbol[N] - symbol[N+1]) The following diagram shows a structure that computes the symbol timing error *at two samples per symbol*. The error is computed once per symbol, but the detector needs to samples per symbol. Hence, there is a downsampling at the end to reduce the output sample rate by half back to the symbol rate. .. figure:: images/lab6-q2-diagram.png :figwidth: 500px :align: center Proceed as follows with the experiment. **Step 1** Configure ``lab6_q1_tx`` in the transmitter and ``lab6_q1_bpsk_rx_zcted`` in the receiver. The error detector code in the receiver is not complete, and you have to further add C code to implement the zero-crossing error detector as described above. Study the complete program ``lab6_q1_bpsk_rx_zcted`` to understand how the error detector is integrated into the receiver. Note that ``lab6_q1_bpsk_rx_zcted`` does not use the external crystal. This guarantees that there is timing drift with respect to the transmitter, which will be visualized in the next step. **Step 2** Run the transmitter and your completed error detector. Set the trigger (Channel 2, Blue) on the Transmitter debug pin (symbol sync) and observe the timing error on the DAC output of the receiver (Channel 1, Orange). Then run a persistent plot. If the experiment is successful, you should be able to obtain a persistent plot similar to the following one. Note that the red pulses indicate the position of the transmitter symbols; it represents the ground truth. The blue curve shows a positive value if the receiver symbol sync comes before the transmitter symbol sync and a negative value if the receiver symbol sync comes after the transmitter symbol sync. This result indicates that the zero-crossing error detector successfully estimates the symbol timing in the signal at the receiver. .. figure:: images/lab6-q2-zcout.png :figwidth: 500px :align: center Our next step will be to build a filter that can use the timing errors to correct the receiver symbol timing. .. important:: **Question 2:** Summarize your findings of the experiments in part 2. Add a listing for Step 1, and add the persistent plot to characterize your symbol timing error detector for Step 2. Part 3: Correcting Symnbol Errors with Interpolation ---------------------------------------------------- Now that we are able to quantify the timing error at the receiver side, we will aim at reconstructing a signal with proper symbol timing (i.e., aligned to the receiver clock). This is done using interpolation. The principle of interpolation is shown below. The ground truth is the transmitter samples x0, x1, x2, x3, x4 in blue. At the receiver, because of a symbol timing error, we actually receive the samples y0, y1, y2, and y3, which are suboptimal to make symbol decisions. Using an interpolator, we will therefore try to reconstruct x-samples using the y samples. The figure shows the example of linear interpolation. For a known timing error, we will compute the i1, i2, i3 samples from the y samples to approximate the x samples (which we don't know at the receiver; we only know the timing error mu). Linear interpolation means that a sample i is a simple linear combination of the two surrounding samples. The timing error mu is a floating-point number between 0 (no timing error) and 1.0 (timing error of 1 sample). .. figure:: images/lab6-q3-ip1.png :figwidth: 500px :align: center For example, from the figure, the following relations can be derived: .. code:: i1 = y1 * mu + y0 * (1 - mu) i2 = y2 * mu + y1 * (1 - mu) i3 = y3 * mu + y2 * (1 - mu) Or in general: .. code:: interpolated_value[n] = sample[n] * mu + sample[n-1] * (1 - mu) The linear interpolator is not perfect; for example it's clear that x1 and x3 are well approximated, but x2 is underestimated. Nevertheless, this interpolation technique is capable of correcting timing errors sufficiently such that the receiver can track the proper symbol sequence. Proceed as follows with the experiment: **Step 1** Configure ``lab6_q1_tx`` in the transmitter and ``lab6_q1_bpsk_rx_zcted`` in the receiver. Edit the receiver code to add the interpolator in the function ``interpolate``. This function is called by the main program at two samples per symbol, so you can directly implement the interpolation formula shown above. Study how the interpolator is controlled using the ``mu_adjust`` function. In particular, each time you press the right button on the receiver, ``mu`` is incremented by a factor of 0.1. ``mu`` wraps around back to 0.0 when it reachs 1.0. This way, you can manually choose between 10 different interpolation levels. **Step 2** Run the receiver and the transmitter. Take the symbol timing of the transmitter (Channel 2, Blue) and observe the DAC output of the receiver (Channel 1, Orange). The DAC output contains the interpolator output. Once the system runs, the transmitter and receiver clocks will slowly drift because of the use of the external crystal for both programs. However, by repeatedly pressing the right button, you should be able to observe an 'open eye' on one of the two samples that are created at the interpolator output for every symbol. By adjusting the interpolator value, you should be able to produce a plot that shows an open eye under the transmitter symbol sync pulse. An example is shown below. Note that the open eye should be with the sample closest to the transmitter symbol sync. .. figure:: images/lab6-q3-ip2.png :figwidth: 500px :align: center .. important:: **Question 3:** Summarize your findings of the experiments in part 3. Add a listing for Step 1, and add the persistent plot to characterize your interpolator for Step 2. Make sure you have manually adjusted the symbol timing (by pressing the right button of the receiver) until you see an open eye under the transmitter sync. Part 4: Automatic Symbol Timing Synchronization ----------------------------------------------- In the final step of the lab, you will combine the zero-crossing timing error detector with the interpolator and a loop filter to obtain automatic symbol timing synchronization. The following figure shows a block diagram of the complete system. All of the blocks except for the loop filter are taken from previous parts of the lab. The timing error detector (ZC-TED) was created in part 2, and the interpolator was created in part 3. Note also that the specific sample rates in this system vary according to the task at hand. The matched filter (RRC) runs at 8 samples per symbol. The interpolator and timing error detector run at 2 samples per symbol. The loop filter runs at 1 sample per symbol; the interpolation value is adjusted only once per symbol. The open receiver eye is taken directly from the interpolator output. This signal can be downsampled to 1 sample per symbol to obtain the actual symbol stream. .. figure:: images/lab6-q4-receiver.png :figwidth: 500px :align: center Proceed as follows with the experiment: **Step 1** Configure ``lab6_q1_tx`` in the transmitter and ``lab6_q1_bpsk_rx_zcted_loop`` in the receiver. There are three functions in the receiver that must be added. The first two, ``zcted`` and ``interpolate``, where created in part 2 and part 3 respectively. The third function, ``loopfilter``, is a simple proportional-integrate controller. It is characterized as follows. ``A`` and ``B`` are two constants that must be chosen to define the control response. As a default choice, use 0.01 for A and 0.5 for B. You may have to experiment with values that work well for your setup. .. code:: state = 0 loopfilter(input) { state = state + input return A * state + B * input } **Step 2** Create a plot of the symbol timing recovery. Take the symbol timing sync (Channel 2, Blue) from the receiver debug pin (since the timing loop will correct symbol timing for us). Take the signal output (Channel 1, Orange) from the receiver DAC. You should be able to show that the receiver properly decodes symbols on an open eye. Moreover, there should be no drift. If you let this design run for a long time, the eye stays open. .. figure:: images/lab6-q4-eye.png :figwidth: 600px :align: center Note that the receiver uses the colored led to hint at the mu values it is using in the interpolator (since printf doesn't work well in real time signal processing). The following codes are used. +----------------+-------------------------------------------+ | Color | Value of mu (interpolator) | +----------------+-------------------------------------------+ | Red | mu < 0 (problematic! should not happen) | +----------------+-------------------------------------------+ | Green | 0 < mu < 0.5 | +----------------+-------------------------------------------+ | Blue | 0.5 < mu < 1.0 | +----------------+-------------------------------------------+ | Off | mu > 1 (problematic! should not happen) | +----------------+-------------------------------------------+ Depending on the long-term drift between receiver clock and transmitter clock, we expect to see either a green led or a blue led, depending on which of the receiver or transmitter is faster. Indeed, the drift will cause the mu must be continuously adjust downward or upward, so that we should see stable blue or stable green. .. important:: **Question 4:** Summarize your findings of the experiments in part 4. Add a listing for the loop filter in Step 1, and add the persistent plot to characterize your interpolator for Step 2. Make sure that the symbol timing (Channel 2, Blue), is taken from the receiver symbol sync. 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. * Follow the principal structure of the report you've used for Lab 3 (taking into account any feedback you have received). * Follow the four questions outlined above to structure your report. 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 github: Use the Team - Share pop-up menu and select your repository for this lab. 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 | 20 | +---------------------------------------------------------+------------+ | Question 2 Analysis | 20 | +---------------------------------------------------------+------------+ | Question 3 Analysis | 20 | +---------------------------------------------------------+------------+ | Question 4 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** | +---------------------------------------------------------+------------+