Friday, November 27, 2020

Hello Radio: How to Listen to FM Radio Using LimeSDR

LimeSDR is an open source software defined radio which can support a continuous frequency range from 100KHz to 3.8GHz. Many wireless systems such as 2/3/4G, Wifi and FM radio are covered in this frequency range, which makes LimeSDR a fairly useful tool.

To test a software defined radio, usually the first experiment to run is to listen to FM radio. FM radio is the equivalent of Hello World in the universe of the software defined radio. Before starting to describe how to run FM radio test, we have a list of HW/SW needed:
1. LimeSDR board with antenna connected
2. FM transmitter which pairs with a smart phone
3. Lime Suite GUI (version 20.10.0)
4. GNU Radio (version 3.7.11)
The test is done using Ubuntu 18.04.4 LTS.

Step 1: LimeSDR configuration file generation

In the test, we will listen to a FM radio channel set at 89.0MHz. Therefore, LimeSDR needs to generate a tone at 89.0MHz, multiply this tone with the input radio signal, and down-convert the ratio signal to the baseband for further processing. To generate this configuration, in Lime Suite GUI -> SXR, Freq needs to be set as 89.0MHz, then calculate and tune. By pressing the "Save" button at the top left of the GUI, the configuration file will be save as fm_receiver_89Mhz.ini for future usage.





















Step 2: GNU Radio set up

GNU Radio is a popular tool for software define radio. To make GNU Radio work together with LimeSDR, one needs to install both GNU Radio and gr-limesdr, a LimeSDR library for GNU Radio. After that, FM_receiver.grc file from /gr-limesdr/examples folder can be loaded into GNU Radio. A few changes need to be made before starting to run it. First, device serial #, .ini file and RF Frequency need to be modified in the LimeSuite Source (RX) module. Device serial # is the serial number for the LimeSDR device and it can be read from Lime Suite GUI; The .ini LimeSDR configuration file has been generated in step 1; RF freq is to be set as 89.0MHz. Baseband Freq in the WX GUI FFT Sink module also needs to be updated to 89.0MHz. Then by pressing the green triangle "Execute the flow graph" button, GNU Radio starts to run. 
























Step 3: Run Test

However, you often only hear noise even if the frequency tuned to is a valid local radio channel. The issue is likely due to antenna setting. A rule of thumb is that the antenna size should be in similar dimension as the wavelength of the wireless signal received. For FM radio at 89.0MHz frequency, the wavelength is 300,000,000/89,000,000 = 3.37 meter. But the antenna bought together with LimeSDR is only 4.5 cm long. The antenna size is too small for FM radio. Based on the antenna length, it is designed for multi-GHz freq signal instead of for FM radio which ranges from 88MHz to 108MHz. There are at least two ways to fix it. The first way is to use a different antenna which is much longer. The second way is to move LimeSDR closer, much closer, to the radio transmitter or the other way around. We use the second way. We bought a FM transmitter which can be plugged into the smart phone and tune it into 89.MHz. Then by putting FW transmitter almost right next to the receiver antenna (shown in the second photo below, the first photo shows the my LimeSDR/antenna and their Lego housing), we can now hear the music. 

Task accomplished!















Tuesday, November 24, 2020

Signal Processing Magic (7) -- Doppler Shift, Rayleigh fading and Jakes model

Doppler shift was discovered by a physicist named Christian Doppler long time ago. Doppler shift is used to characterize the frequency change due to movement. A typical example is that when a fire truck drives toward you, the tone of its siren changes over the time because its speed towards you varies.

Doppler shift for wireless communication is

\[f_d=v/c*f_c\]

whereas v is the speed of the object, c is the speed of light, and \(f_c\) is carrier frequency. For instance, if you sit on a high-speed training moving at 350km/h browsing Internet and your phone is using a 3GHz band, then 

\[f_d = (350*1000/3600)/(3*10e8)*3*10e9 = 972 Hz\]

Based on this equation, moving faster as well as using a band with higher carrier frequency will make Doppler shift larger. Usually the highest Doppler shift is observed in high-speed train. Larger Doppler shift makes channel estimation harder in wireless communication.

Rayleigh fading is a commonly used model for a wireless channel, and it is used when the transmitter can't see the receiver such as in Manhattan island. Rayleigh fading model can be derived from joint Gaussian distribution. Assuming \(x\) and \(y\) are two zero-mean Gaussian R.V. orthogonal to each other, their joint distribution becomes:

\[f_{X,Y}(x,y)=\frac{1}{2\pi\sigma^{2}}e^{-\frac{x^2+y^2}{2\sigma^2}}\]

Rayleigh fading tracks the envelope, \(r\). With \(r^2=x^2+y^2\), we have \(x=r*cos(\theta)\) and \(y=r*sin(\theta)\). To transfer a \(f_{X,Y}(x,y)\) to distribution of \(r\), the determinant of the Jacobian matrix needs to be found:

\[J(r,\theta)=det\begin{bmatrix}\frac{\partial x}{\partial r}&\frac{\partial x}{\partial \theta}\\\frac{\partial y}{\partial r}&\frac{\partial y}{\partial \theta}\end{bmatrix}=det\begin{bmatrix}cos(\theta)&-r*sin(\theta)\\sin(\theta)&r*cos(\theta)\end{bmatrix}=r\]

Therefore,

\[f_{R,\Theta}(r,\theta)=\frac{J(r,\theta)}{2\pi\sigma^{2}}e^{-\frac{r^2}{2\sigma^2}}=\frac{r}{2\pi\sigma^{2}}e^{-\frac{r^2}{2\sigma^2}}\]

After integrating over \(2\pi\) to remove \(\theta\), Rayleigh fading model is:

\[f_{R}(r)=\frac{r}{\sigma^{2}}e^{-\frac{r^2}{2\sigma^2}}\] 

for \(r\geq0\).


In reality, fading channel is always correlated in time. That means the wireless channels your phone sees in this moment and the next moment are always more or less similar. Fourier transmission of wireless channel's time-domain auto-correlation becomes its Power Spectral Density (PSD). For Rayleigh fading with vertical antenna and signal coming from all angles in uniform distribution, it has a famous PSD called Jakes model. Jakes model also depends on Doppler shift, and it is:

\[S(f)=\frac{1}{\pi f_d}\frac{1}{\sqrt{1-(f/f_d)^2}}\]

when \(|f|\leq f_d\) and \(S(f)=0\) otherwise. Jakes model has a famous U shape and the width of the "U" depends on Doppler shift, \(f_d\). When \(f_d=0\), Jakes model is an impulse and it means Rayleigh channel never changes.


Low Light Image Combining Using Python (3) -- Running Even Faster

In this blog, we will discuss how to make lower light image combining run even faster. 

Image alignment is the most time-consuming stage of low light image combining. By using a method similar to what has been proposed in HDR+ project page (https://www.timothybrooks.com/tech/hdr-plus/), we introduce decimation to image alignment and it brings big saving in calculation time.

This is how decimation helps: as discussed earlier, assume block size is B, search range in both horizontal and vertical S, the complexity of image alignment is proportional to B*S*S. For a 4k x 3k image and search range equal to 40 ([-40,40] with each even position), the complexity for matching each pair is 19.2G operations, which is enormous. To save MIPS, we can divide this process to two steps:

Step 1: decimate the image by 16. After decimation, it becomes much easier to align images with the cost of reduced accuracy. The complexity of step 1 now becomes B/16*S*S.

Step 2: we are not done yet. Decimating the original image by 16 means aggregating 16 pixels of the original pixel to one. Now it is time to find out exactly which one of these 16 pixels provides the best alignment so that there is no sacrifice on accuracy. But the search range is drastically reduced. We now align with original image with size B but less range with new S' = 4. S' = 4 is sufficient to find one out of 16 pixel candidates.

Breaking the original image alignment to two steps reduces MIPS quite a bit: instead of B*S*S = 19.2G, now we have B/16*S*S + B*4*4 = 1.39G, a reduction of 93% of complexity. 

By our experiment, the new execution time of the whole image combining process becomes 9.7s without any help from multicore, which is a roughly 1/4 of the baseline. The sample code can be found here: https://github.com/legendzhangn/blog/tree/master/lowlight_image_combine_even_faster