OFDM
For real OFDM look at the DRM system, an open source receiver
available from sourceforge
and get technical specification TS 101 980 from the European Telecommunications Standards Institute.
This is an experiment in feeding 8 signal sources of varying pulse
widths to an inverse DFT to see the spectrum and get an idea of
the orthogonality of it. We create 8 vectors of size 32, and
vary the duty cycle from 3-on, 29-off (9%) to 24-on, 8-off (75%) in steps of 3,
and look at the resulting spectrum and how they interact. We are
also exploring ways of feeding a meangingful parallel signal to the iDFT.
This setup creates 8 vector sources, interleaves them, then feed that to
a serial-to-parallel which separates them out again for iDFT. That is
followed by a parallel-to-serial, a 250Khz mixer to shift the band up from
all negative frequencies, then the usual fft-sink, for display.
BTW, I laid out some cash for "OFDM for Wireless Communications Systems" (Ramjee Prasad) only to find an important chapter online in pdf form here
The code:
#!/usr/bin/env python
#
from gnuradio import gr
from gnuradio import eng_notation
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import stdgui, fftsink
from optparse import OptionParser
import wx, random
class app_flow_graph (stdgui.gui_flow_graph):
def __init__(self, frame, panel, vbox, argv):
stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
self.frame = frame
self.panel = panel
sample_rate = 500e3
fft_size = 8
# create 8 vectors of varying duty-cycle
# using tvec to create temporary data, then append
# that list to vecs where it can be easily accessed
vecs = []
for i in range(1,9):
tvec = []
for k in range(0,3*i):
tvec += [1]
for k in range(3*i+1,32):
tvec += [0]
vecs += [tvec]
# some different signals to play with
thin = []
for i in range(0,3):
thin += [1]
for i in range(4,32):
thin += [0]
fat = []
for i in range(0,28):
fat += [1]
for i in range(29,32):
fat += [0]
fast = []
for i in range(0,4):
fast += [1, 1, 1, 1, 0, 0, 0, 0]
pwm = [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,0,1,0,1,0]
randvec = []
for i in range(0,32):
if random.random() > .5:
randvec += [1]
else:
randvec += [0]
faster = []
for i in range(0,8):
faster += [1, 1, 0, 0]
ultra_fast = []
for i in range(0,16):
ultra_fast += [1, 0]
src1 = gr.vector_source_c(vecs[0],1)
src2 = gr.vector_source_c(vecs[1],1)
src3 = gr.vector_source_c(vecs[2],1)
src4 = gr.vector_source_c(vecs[3],1)
src5 = gr.vector_source_c(vecs[4],1)
src6 = gr.vector_source_c(vecs[5],1)
src7 = gr.vector_source_c(vecs[6],1)
src8 = gr.vector_source_c(vecs[7],1)
inter = gr.interleave(gr.sizeof_gr_complex)
self.connect ( src1, (inter, 0))
self.connect ( src2, (inter, 1))
self.connect ( src3, (inter, 2))
self.connect ( src4, (inter, 3))
self.connect ( src5, (inter, 4))
self.connect ( src6, (inter, 5))
self.connect ( src7, (inter, 6))
self.connect ( src8, (inter, 7))
s2p = gr.serial_to_parallel (gr.sizeof_gr_complex, fft_size)
ifft1 = gr.fft_vcc (fft_size,False,False) # inverse, no windowing
p2s = gr.parallel_to_serial (gr.sizeof_gr_complex, fft_size)
rf_src = gr.sig_source_c (sample_rate,gr.GR_SIN_WAVE,250e3,1,0)
rf_mix = gr.multiply_cc()
self.connect ( inter, s2p )
self.connect ( s2p, ifft1 )
self.connect ( ifft1, p2s )
self.connect ( p2s, (rf_mix, 0))
self.connect ( rf_src, (rf_mix, 1))
block, fft_win = fftsink.make_fft_sink_c (self, panel, "", 256, sample_rate)
self.connect (rf_mix, block)
vbox.Add (fft_win, 1, wx.EXPAND)
def main ():
app = stdgui.stdapp (app_flow_graph, "USRP FFT")
app.MainLoop ()
if __name__ == '__main__':
main ()
which produces this output:
The thin, low duty-cycle signal is the fat, wide spectrum on the left,
while the high duty-cycle signal is the narrower peaks on the right -
that is, a constant on signal is a narrow peak, while a more highly
modulated signal is wider. If we change all signals to short pulses
we get this:
then just for grins put a wide signal in there somewhere:
where we can see sig source #6 has changed to a peaked spectrum. Finally, putting
signal 'fast' in the source 3 slot we get this:
were we see they are still largely non-interfering with each other. Next add
pulse-width-modulation to slot 4:
then a random noise vector in slot 8:
then a medium fast signal [1,1,0,0,1,1,0,0,...] in slot 7:
note the two peaks on each side of the cntral peak in slot 7. Finally
the fastest possible signal in 7:
note the peaks are further apart. What if we put two ultra-fast signals
in adjacent slots? Trying 7 & 8:
appearently they are interfering with each other at that rate, as the side
peaks are overlapping on the common channel boundary just above 150Khz.