FM transmission on many channels using gnuradio

From Opendigitalradio
Revision as of 19:20, 2 January 2010 by Coinchon (Talk | contribs)

Jump to: navigation, search

FM transmitter on many channels using gnuradio.

Tools needed:

  • gnuradio 3.2
  • grc (gnuradio companion)
  • mpg123
  • USRP


In this example we will show how to make an FM software transmitter broadcasting simultaneously on many channels. Look at GRC schema or use directly python code below.

Python code

#!/usr/bin/env python
##################################################
# Gnuradio Python Flow Graph
# Title: Multiplex frequencies FM transmitter
# Author: Mathias Coinchon
# Generated: Sat Jan  2 19:19:17 2010
##################################################

from gnuradio import blks2
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.gr import firdes
from gnuradio.wxgui import fftsink2
from gnuradio.wxgui import forms
from grc_gnuradio import usrp as grc_usrp
from grc_gnuradio import wxgui as grc_wxgui
from optparse import OptionParser
import wx

class MF_FM_TX(grc_wxgui.top_block_gui):

	def __init__(self):
		grc_wxgui.top_block_gui.__init__(self, title="Multiplex frequencies FM transmitter")

		##################################################
		# Variables
		##################################################
		self.samp_rate = samp_rate = 32000
		self.quad_rate = quad_rate = 1280000
		self.carrier2_frequency = carrier2_frequency = 300000
		self.carrier1_frequency = carrier1_frequency = -300000
		self.FM_frequency = FM_frequency = 107600000

		##################################################
		# Controls
		##################################################
		_carrier2_frequency_sizer = wx.BoxSizer(wx.VERTICAL)
		self._carrier2_frequency_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_carrier2_frequency_sizer,
			value=self.carrier2_frequency,
			callback=self.set_carrier2_frequency,
			label="Carrier 2 Frequency",
			converter=forms.float_converter(),
			proportion=0,
		)
		self._carrier2_frequency_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_carrier2_frequency_sizer,
			value=self.carrier2_frequency,
			callback=self.set_carrier2_frequency,
			minimum=-500000,
			maximum=500000,
			num_steps=100,
			style=wx.SL_HORIZONTAL,
			cast=float,
			proportion=1,
		)
		self.Add(_carrier2_frequency_sizer)
		_carrier1_frequency_sizer = wx.BoxSizer(wx.VERTICAL)
		self._carrier1_frequency_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_carrier1_frequency_sizer,
			value=self.carrier1_frequency,
			callback=self.set_carrier1_frequency,
			label="Carrier 1 Frequency",
			converter=forms.float_converter(),
			proportion=0,
		)
		self._carrier1_frequency_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_carrier1_frequency_sizer,
			value=self.carrier1_frequency,
			callback=self.set_carrier1_frequency,
			minimum=-500000,
			maximum=500000,
			num_steps=100,
			style=wx.SL_HORIZONTAL,
			cast=float,
			proportion=1,
		)
		self.Add(_carrier1_frequency_sizer)
		_FM_frequency_sizer = wx.BoxSizer(wx.VERTICAL)
		self._FM_frequency_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_FM_frequency_sizer,
			value=self.FM_frequency,
			callback=self.set_FM_frequency,
			label="Central FM frequency",
			converter=forms.float_converter(),
			proportion=0,
		)
		self._FM_frequency_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_FM_frequency_sizer,
			value=self.FM_frequency,
			callback=self.set_FM_frequency,
			minimum=87500000,
			maximum=108000000,
			num_steps=205,
			style=wx.SL_HORIZONTAL,
			cast=float,
			proportion=1,
		)
		self.Add(_FM_frequency_sizer)

		##################################################
		# Blocks
		##################################################
		self.blks2_rational_resampler_xxx_0 = blks2.rational_resampler_ccc(
			interpolation=4,
			decimation=1,
			taps=None,
			fractional_bw=None,
		)
		self.blks2_wfm_tx_0 = blks2.wfm_tx(
			audio_rate=samp_rate,
			quad_rate=320000,
			tau=50e-6,
			max_dev=75e3,
		)
		self.gr_add_xx_0 = gr.add_vcc(1)
		self.gr_multiply_const_vxx_0 = gr.multiply_const_vcc((5000, ))
		self.gr_multiply_xx_0 = gr.multiply_vcc(1)
		self.gr_multiply_xx_1 = gr.multiply_vcc(1)
		self.gr_sig_source_x_0 = gr.sig_source_c(quad_rate, gr.GR_COS_WAVE, carrier1_frequency, 1, 0)
		self.gr_sig_source_x_1 = gr.sig_source_c(quad_rate, gr.GR_COS_WAVE, carrier2_frequency, 1, 0)
		self.gr_wavfile_source_0 = gr.wavfile_source("/home/mc/FM_demo/test_32k_mono.wav", True)
		self.usrp_simple_sink_x_0 = grc_usrp.simple_sink_c(which=0, side="B")
		self.usrp_simple_sink_x_0.set_interp_rate(100)
		self.usrp_simple_sink_x_0.set_frequency(-FM_frequency, verbose=True)
		self.usrp_simple_sink_x_0.set_gain(0)
		self.wxgui_fftsink2_0 = fftsink2.fft_sink_c(
			self.GetWin(),
			baseband_freq=0,
			y_per_div=10,
			y_divs=10,
			ref_level=50,
			sample_rate=quad_rate,
			fft_size=1024,
			fft_rate=30,
			average=False,
			avg_alpha=None,
			title="FFT Plot",
			peak_hold=False,
		)
		self.Add(self.wxgui_fftsink2_0.win)

		##################################################
		# Connections
		##################################################
		self.connect((self.gr_wavfile_source_0, 0), (self.blks2_wfm_tx_0, 0))
		self.connect((self.gr_multiply_const_vxx_0, 0), (self.usrp_simple_sink_x_0, 0))
		self.connect((self.gr_multiply_xx_0, 0), (self.gr_add_xx_0, 0))
		self.connect((self.gr_add_xx_0, 0), (self.gr_multiply_const_vxx_0, 0))
		self.connect((self.gr_add_xx_0, 0), (self.wxgui_fftsink2_0, 0))
		self.connect((self.blks2_wfm_tx_0, 0), (self.blks2_rational_resampler_xxx_0, 0))
		self.connect((self.blks2_rational_resampler_xxx_0, 0), (self.gr_add_xx_0, 1))
		self.connect((self.gr_multiply_xx_1, 0), (self.gr_add_xx_0, 2))
		self.connect((self.gr_sig_source_x_1, 0), (self.gr_multiply_xx_1, 1))
		self.connect((self.blks2_rational_resampler_xxx_0, 0), (self.gr_multiply_xx_1, 0))
		self.connect((self.blks2_rational_resampler_xxx_0, 0), (self.gr_multiply_xx_0, 1))
		self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_0, 0))

	def set_samp_rate(self, samp_rate):
		self.samp_rate = samp_rate

	def set_quad_rate(self, quad_rate):
		self.quad_rate = quad_rate
		self.wxgui_fftsink2_0.set_sample_rate(self.quad_rate)
		self.gr_sig_source_x_1.set_sampling_freq(self.quad_rate)
		self.gr_sig_source_x_0.set_sampling_freq(self.quad_rate)

	def set_carrier2_frequency(self, carrier2_frequency):
		self.carrier2_frequency = carrier2_frequency
		self._carrier2_frequency_slider.set_value(self.carrier2_frequency)
		self._carrier2_frequency_text_box.set_value(self.carrier2_frequency)
		self.gr_sig_source_x_1.set_frequency(self.carrier2_frequency)

	def set_carrier1_frequency(self, carrier1_frequency):
		self.carrier1_frequency = carrier1_frequency
		self._carrier1_frequency_slider.set_value(self.carrier1_frequency)
		self._carrier1_frequency_text_box.set_value(self.carrier1_frequency)
		self.gr_sig_source_x_0.set_frequency(self.carrier1_frequency)

	def set_FM_frequency(self, FM_frequency):
		self.FM_frequency = FM_frequency
		self._FM_frequency_slider.set_value(self.FM_frequency)
		self._FM_frequency_text_box.set_value(self.FM_frequency)
		self.usrp_simple_sink_x_0.set_frequency(-self.FM_frequency)

if __name__ == '__main__':
	parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
	(options, args) = parser.parse_args()
	tb = MF_FM_TX()
	tb.Run(True)
Personal tools