3 from gnuradio import gr
4 from gnuradio import audio
5 from gnuradio import mc4020
8 def high_speed_adc (fg, input_rate):
9 # return gr.file_source (gr.sizeof_short, "dummy.dat", False)
10 return mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V)
13 # return a gr.flow_graph
15 def build_graph (freq1, freq2):
20 quad_rate = input_rate / cfir_decimation
21 audio_rate = quad_rate / audio_decimation
25 # use high speed ADC as input source
26 src = high_speed_adc (fg, input_rate)
28 # compute FIR filter taps for channel selection
30 gr.firdes.low_pass (1.0, # gain
31 input_rate, # sampling rate
32 250e3, # low pass cutoff freq
33 8*100e3, # width of trans. band
34 gr.firdes.WIN_HAMMING)
36 # input: short; output: complex
38 gr.freq_xlating_fir_filter_scf (cfir_decimation,
40 freq1, # 1st station freq
43 (head1, tail1) = build_pipeline (fg, quad_rate, audio_decimation)
45 # sound card as final sink
46 audio_sink = audio.sink (int (audio_rate))
48 # now wire it all together
49 fg.connect (src, chan_filter1)
50 fg.connect (chan_filter1, head1)
51 fg.connect (tail1, (audio_sink, 0))
53 # two stations at once?
55 # Extract the second station and connect
56 # it to a second pipeline...
58 # input: short; output: complex
60 gr.freq_xlating_fir_filter_scf (cfir_decimation,
62 freq2, # 2nd station freq
65 (head2, tail2) = build_pipeline (fg, quad_rate, audio_decimation)
67 fg.connect (src, chan_filter2)
68 fg.connect (chan_filter2, head2)
69 fg.connect (tail2, (audio_sink, 1))
73 def build_pipeline (fg, quad_rate, audio_decimation):
74 '''Given a flow_graph, fg, construct a pipeline
75 for demodulating a broadcast FM signal. The
76 input is the downconverteed complex baseband
77 signal. The output is the demodulated audio.
79 build_pipeline returns a two element tuple
80 containing the input and output endpoints.
82 fm_demod_gain = 2200.0/32768.0
83 audio_rate = quad_rate / audio_decimation
86 # input: complex; output: float
87 fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain)
89 # compute FIR filter taps for audio filter
90 width_of_transition_band = audio_rate / 32
91 audio_coeffs = gr.firdes.low_pass (1.0, # gain
92 quad_rate, # sampling rate
93 audio_rate/2 - width_of_transition_band,
94 width_of_transition_band,
95 gr.firdes.WIN_HAMMING)
97 # input: float; output: float
98 audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
100 fg.connect (fm_demod, audio_filter)
101 return ((fm_demod, 0), (audio_filter, 0))
107 freq1 = float (args[0]) * 1e6
110 freq1 = float (args[0]) * 1e6
111 freq2 = float (args[1]) * 1e6
113 sys.stderr.write ('usage: fm_demod freq1 [freq2]\n')
116 # connect to RF front end
117 rf_front_end = gr.microtune_4937_eval_board ()
118 if not rf_front_end.board_present_p ():
119 raise IOError, 'RF front end not found'
122 rf_front_end.set_AGC (300)
123 IF_freq = rf_front_end.get_output_freq ()
126 if not freq2: # one station
128 rf_front_end.set_RF_freq (freq1)
129 fg = build_graph (IF_freq, None)
133 if abs (freq1 - freq2) > 5.5e6:
134 raise IOError, 'freqs too far apart'
136 target_freq = (freq1 + freq2) / 2
137 actual_freq = rf_front_end.set_RF_freq (target_freq)
138 #actual_freq = target_freq
140 fg = build_graph (IF_freq + freq1 - actual_freq,
141 IF_freq + freq2 - actual_freq)
143 fg.start () # fork thread(s) and return
144 raw_input ('Press Enter to quit: ')
147 if __name__ == '__main__':