{
"metadata": {
"name": ""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Lab 2: Time-Frequency part II, Calibration of the SDR frequency using GSM signals
\n",
"\n",
"\n",
"\n",
"\n",
"### Michael Lustig \n",
"\n",
"Note: The instruction in this lab are now less detailed and require though and common sense with respect to choosing parameters and implementations.\n",
"\n",
"* The lab was inspired by the Kalibrate project by Joshua Lackey\n",
"\n",
"We hope you enjoy it!\n",
"\n"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Import general functions and libraries\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import pyaudio\n",
"from numpy import pi\n",
"from numpy import sin\n",
"from numpy import zeros\n",
"from numpy import ones\n",
"from numpy import r_\n",
"from scipy import signal\n",
"\n",
"from numpy import hanning\n",
"from numpy import outer\n",
"\n",
"from rtlsdr import RtlSdr\n",
"from numpy import mean\n",
"from numpy import power\n",
"from numpy.fft import fft\n",
"from numpy.fft import fftshift\n",
"from numpy.fft import ifft\n",
"from numpy.fft import ifftshift\n",
"\n",
"from numpy import isreal\n",
"\n",
"\n",
"\n",
"%matplotlib inline"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# function to compute average power spectrum\n",
"def avgPS( x, N=256, fs=1):\n",
" M = floor(len(x)/N)\n",
" x_ = reshape(x[:M*N],(M,N)) * np.hamming(N)[None,:]\n",
" X = np.fft.fftshift(np.fft.fft(x_,axis=1),axes=1)\n",
" return r_[-N/2.0:N/2.0]/N*fs, mean(abs(X**2),axis=0)\n",
"\n",
"\n",
"# Plot an image of the spectrogram y, with the axis labeled with time tl,\n",
"# and frequency fl\n",
"#\n",
"# t_range -- time axis label, nt samples\n",
"# f_range -- frequency axis label, nf samples\n",
"# y -- spectrogram, nf by nt array\n",
"# dbf -- Dynamic range of the spect\n",
"\n",
"def sg_plot( t_range, f_range, y, dbf = 60) :\n",
" eps = 1e-3\n",
" \n",
" # find maximum\n",
" y_max = abs(y).max()\n",
" \n",
" # compute 20*log magnitude, scaled to the max\n",
" y_log = 20.0 * np.log10( abs( y ) / y_max + eps )\n",
" \n",
" fig=figure(figsize=(15,6))\n",
" \n",
" plt.imshow( np.flipud( 64.0*(y_log + dbf)/dbf ), extent= t_range + f_range ,cmap=plt.cm.gray, aspect='auto')\n",
" plt.xlabel('Time, s')\n",
" plt.ylabel('Frequency, Hz')\n",
" plt.tight_layout()\n",
"\n",
"\n",
"def myspectrogram_hann_ovlp(x, m, fs, fc,dbf = 60):\n",
" # Plot the spectrogram of x.\n",
" # First take the original signal x and split it into blocks of length m\n",
" # This corresponds to using a rectangular window %\n",
" \n",
" \n",
" isreal_bool = isreal(x).all()\n",
" \n",
" # pad x up to a multiple of m \n",
" lx = len(x);\n",
" nt = (lx + m - 1) // m\n",
" x = append(x,zeros(-lx+nt*m))\n",
" x = x.reshape((m/2,nt*2), order='F')\n",
" x = concatenate((x,x),axis=0)\n",
" x = x.reshape((m*nt*2,1),order='F')\n",
" x = x[r_[m//2:len(x),ones(m//2)*(len(x)-1)].astype(int)].reshape((m,nt*2),order='F')\n",
" \n",
" \n",
" xmw = x * hanning(m)[:,None];\n",
" \n",
" \n",
" # frequency index\n",
" t_range = [0.0, lx / fs]\n",
" \n",
" if isreal_bool:\n",
" f_range = [ fc, fs / 2.0 + fc]\n",
" xmf = np.fft.fft(xmw,len(xmw),axis=0)\n",
" sg_plot(t_range, f_range, xmf[0:m/2,:],dbf=dbf)\n",
" print 1\n",
" else:\n",
" f_range = [-fs / 2.0 + fc, fs / 2.0 + fc]\n",
" xmf = np.fft.fftshift( np.fft.fft( xmw ,len(xmw),axis=0), axes=0 )\n",
" sg_plot(t_range, f_range, xmf,dbf = dbf)\n",
" \n",
" return t_range, f_range, xmf"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## RTL-SDR frequency Drift\n",
"\n",
"The rtl-sdr has has a 28.8MHz crystal oscillator, which sets the reference frequency used for demodulation on the tuner. The crystal is known to have poor quallity and therefor its frequency can drift considerably with temperature. The drift is measured in parts per millions (PPM) and can go up to $\\pm50$ PPM. The result of such a drift is that when you tune to a certain frequency, you will actually be tunning to an offset frequency. This offset is proportional to the center frequency and gets worse for higher frequencies. \n",
"\n",
"This sort of oscillator drifts are very common in other devices, such as your cellphone. The wireless industry has come up with many different techniques in which the clock, or the absolute frequency can be corrected for. In this lab we will use the GSM cellphone network to correct for the frequency drift of the rtl-sdr. GSM base stations are required to have an accurate clock within 0.05 ppm, so they are an excellent source of \"accurate\" signals. This is very much the first step that a GSM based phone would do in order to connect to the network. \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## GSM : Global System for Mobile Communications\n",
"\n",
"This section is heavily based on \"GSM for dummies\" (http://www.pennula.de/datenarchiv/gsm-for-dummies.pdf)\n",
"\n",
"GSM is a popular digital cellular network. It is based on time-division-multiple-access (TDMA). GSM operates in several different carrier frequencies. In the US and Canada and number of other countries, the frequency bands are 850MHz and 1900MHz. In this lab we will use the 850MHz frequency band, since for the majority of you with 820T tuners the 1900MHz band is outside of the rtl-sdr range. \n",
"\n",
"### Frequencies\n",
"For the GSM-850 the band is separated into Uplink frequencies 824-849MHz and downlink frequencies 869-894MHz. The base station transmits on the downlink frequencies and mobile phones transmit on the uplink frequencies. GSM operates in duplex mode in which the phone and base station receive and transmit at the same time. This is the reason that the uplink and the downlink are separated by 50MHz!. A channel number, also known as Absolute Radio Frequency Channel Number (ARFCN) is assigned a pair of uplink and downlink frequencies. There are 124 channels numbered 128-251 in the GSM-850 system. Each channel is allocated a bandwidth of 200KHz. For the downlink frequencies $f_N = 869.2+0.2*(ARFCN-128)$ MHz. \n",
"\n",
"### Modulation\n",
"GSM uses Gaussian Minimum Shift Keying (GMSK in short) as a modulation method. It is a binary digital Frequency Modulated scheme in which the phase between each bit period is continuouse. Bits are encoded as different frequencies separated by one-half the bit-rate. The modulation rate in GSM is $1625/6 \\approx 270.833$ kb/s. For more information read (http://en.wikipedia.org/wiki/Minimum-shift_keying) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Time-Division-Multiple-Acess\n",
"\n",
"GSM uses time-division to share a frequency channel among users. Each frequency is divided into blocks of time that are known as time-slots. There are 8 time-slots that are numberes TS0 - TS7. Each time-slot lasts about 576.9 $\\mu s$. Given the bit-rate above, a total of 156.25 bits can be transmitted in each slot. Each slot allocates 8.25 of it \"bits time\" as guard-time, split between the beginning and the end of each time-slot. This time is necessary to prevent overlapping between the different time slots. In addition, 3 bits on both sides of the time-slot do not contain any data and are there to allow for ramping the amplifiers up and down. \n",
"\n",
"Data transmitted within each time-slot is called a burst. There are several type of burts, with different purposes. We are interested in a frequency correction burst, which is a burst of pure frequency at 1/4th the bitrate of GSM or (1625000 / 6) / 4 = 67708.3 Hz. \n",
"\n",
"\n",
"