46ebfe94ab0c69927d3138febef71f085ed4d2fb
[debian/gnuradio] / gr-qtgui / src / python / usrp2_display.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2009 Free Software Foundation, Inc.
4
5 # This file is part of GNU Radio
6
7 # GNU Radio is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3, or (at your option)
10 # any later version.
11
12 # GNU Radio is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License
18 # along with GNU Radio; see the file COPYING.  If not, write to
19 # the Free Software Foundation, Inc., 51 Franklin Street,
20 # Boston, MA 02110-1301, USA.
21
22
23 from gnuradio import gr
24 from gnuradio import usrp2
25 from gnuradio import eng_notation
26 from gnuradio.eng_option import eng_option
27 from gnuradio.qtgui import qtgui
28 from optparse import OptionParser
29 import sys
30
31 try:
32     from gnuradio.qtgui import qtgui
33     from PyQt4 import QtGui, QtCore
34     import sip
35 except ImportError:
36     print "Please install gr-qtgui."
37     sys.exit(1)
38
39 try:
40     from usrp_display_qtgui import Ui_MainWindow
41 except ImportError:
42     print "Error: could not find usrp_display_qtgui.py:"
43     print "\t\"pyuic4 usrp_display_qtgui.ui -o usrp_display_qtgui.py\""
44     sys.exit(1)
45
46
47 # ////////////////////////////////////////////////////////////////////
48 #        Define the QT Interface and Control Dialog
49 # ////////////////////////////////////////////////////////////////////
50
51
52 class main_window(QtGui.QMainWindow):
53     def __init__(self, snk, fg, parent=None):
54
55         QtGui.QWidget.__init__(self, parent)
56         self.gui = Ui_MainWindow()
57         self.gui.setupUi(self)
58
59         self.fg = fg
60
61         # Add the qtsnk widgets to the layout box
62         self.gui.sinkLayout.addWidget(snk)
63
64         self.gui.dcGainEdit.setText(QtCore.QString("%1").arg(0.001))
65
66         # Connect up some signals
67         self.connect(self.gui.pauseButton, QtCore.SIGNAL("clicked()"),
68                      self.pauseFg)
69         self.connect(self.gui.frequencyEdit, QtCore.SIGNAL("editingFinished()"),
70                      self.frequencyEditText)
71         self.connect(self.gui.gainEdit, QtCore.SIGNAL("editingFinished()"),
72                      self.gainEditText)
73         self.connect(self.gui.bandwidthEdit, QtCore.SIGNAL("editingFinished()"),
74                      self.bandwidthEditText)
75         self.connect(self.gui.amplifierEdit, QtCore.SIGNAL("editingFinished()"),
76                      self.amplifierEditText)
77
78         self.connect(self.gui.actionSaveData, QtCore.SIGNAL("activated()"),
79                      self.saveData)
80         self.gui.actionSaveData.setShortcut(QtGui.QKeySequence.Save)
81
82         self.connect(self.gui.dcGainEdit, QtCore.SIGNAL("editingFinished()"),
83                      self.dcGainEditText)
84         self.connect(self.gui.dcCancelCheckBox, QtCore.SIGNAL("clicked(bool)"),
85                      self.dcCancelClicked)
86
87     def pauseFg(self):
88         if(self.gui.pauseButton.text() == "Pause"):
89             self.fg.stop()
90             self.fg.wait()
91             self.gui.pauseButton.setText("Unpause")
92         else:
93             self.fg.start()
94             self.gui.pauseButton.setText("Pause")
95       
96
97     # Functions to set the values in the GUI
98     def set_frequency(self, freq):
99         self.freq = freq
100         sfreq = eng_notation.num_to_str(self.freq)
101         self.gui.frequencyEdit.setText(QtCore.QString("%1").arg(sfreq))
102         
103     def set_gain(self, gain):
104         self.gain = gain
105         self.gui.gainEdit.setText(QtCore.QString("%1").arg(self.gain))
106
107     def set_bandwidth(self, bw):
108         self.bw = bw
109         sbw = eng_notation.num_to_str(self.bw)
110         self.gui.bandwidthEdit.setText(QtCore.QString("%1").arg(sbw))
111
112     def set_amplifier(self, amp):
113         self.amp = amp
114         self.gui.amplifierEdit.setText(QtCore.QString("%1").arg(self.amp))
115
116
117     # Functions called when signals are triggered in the GUI
118     def frequencyEditText(self):
119         try:
120             freq = eng_notation.str_to_num(self.gui.frequencyEdit.text().toAscii()) 
121             self.fg.set_frequency(freq)
122             self.freq = freq
123         except RuntimeError:
124             pass
125
126     def gainEditText(self):
127         try:
128             gain = float(self.gui.gainEdit.text())
129             self.fg.set_gain(gain)
130             self.gain = gain
131         except ValueError:
132             pass
133                 
134     def bandwidthEditText(self):
135         try:
136             bw = eng_notation.str_to_num(self.gui.bandwidthEdit.text().toAscii())
137             self.fg.set_bandwidth(bw)
138             self.bw = bw
139         except ValueError:
140             pass
141         
142     def amplifierEditText(self):
143         try:
144             amp = float(self.gui.amplifierEdit.text())
145             self.fg.set_amplifier_gain(amp)
146             self.amp = amp
147         except ValueError:
148             pass
149
150     def saveData(self):
151         fileName = QtGui.QFileDialog.getSaveFileName(self, "Save data to file", ".");
152         if(len(fileName)):
153             self.fg.save_to_file(str(fileName))
154
155     def dcGainEditText(self):
156         gain = float(self.gui.dcGainEdit.text())
157         self.fg.set_dc_gain(gain)
158         
159     def dcCancelClicked(self, state):
160         self.dcGainEditText()
161         self.fg.cancel_dc(state)
162         
163
164         
165 class my_top_block(gr.top_block):
166     def __init__(self):
167         gr.top_block.__init__(self)
168
169         parser = OptionParser(option_class=eng_option)
170         parser.add_option("-e", "--interface", type="string", default="eth0",
171                           help="select Ethernet interface, default is eth0")
172         parser.add_option("-m", "--mac-addr", type="string", default="",
173                           help="select USRP by MAC address, default is auto-select")
174         parser.add_option("-W", "--bw", type="float", default=1e6,
175                           help="set bandwidth of receiver [default=%default]")
176         parser.add_option("-f", "--freq", type="eng_float", default=None,
177                           help="set frequency to FREQ", metavar="FREQ")
178         parser.add_option("-g", "--gain", type="eng_float", default=None,
179                           help="set gain in dB (default is midpoint)")
180         parser.add_option("--fft-size", type="int", default=2048,
181                           help="Set number of FFT bins [default=%default]")
182         (options, args) = parser.parse_args()
183
184         if len(args) != 0:
185             parser.print_help()
186             sys.exit(1)
187         self.options = options
188         self.show_debug_info = True
189         
190         self.qapp = QtGui.QApplication(sys.argv)
191
192         self.u = usrp2.source_32fc(options.interface, options.mac_addr)
193         self._adc_rate = self.u.adc_rate()
194         self.set_bandwidth(options.bw)
195
196         if options.gain is None:
197             # if no gain was specified, use the mid-point in dB
198             g = self.u.gain_range()
199             options.gain = float(g[0]+g[1])/2
200         self.set_gain(options.gain)
201
202         if options.freq is None:
203             # if no frequency was specified, use the mid-point of the subdev
204             f = self.u.freq_range()
205             options.freq = float(f[0]+f[1])/2
206         self.set_frequency(options.freq)
207
208         self._fftsize = options.fft_size
209
210         self.snk = qtgui.sink_c(options.fft_size, gr.firdes.WIN_BLACKMAN_hARRIS,
211                                 self._freq, self._bandwidth,
212                                 "USRP2 Display",
213                                 True, True, False, True, False)
214
215         # Set up internal amplifier
216         self.amp = gr.multiply_const_cc(0.0)
217         self.set_amplifier_gain(100)
218
219         # Create a single-pole IIR filter to remove DC
220         #   but don't connect it yet
221         self.dc_gain = 0.001
222         self.dc = gr.single_pole_iir_filter_cc(self.dc_gain)
223         self.dc_sub = gr.sub_cc()
224
225         self.connect(self.u, self.amp, self.snk)
226
227         if self.show_debug_info:
228             print "Decimation rate: ", self._decim
229             print "Bandwidth: ", self._bandwidth
230             print "D'board: ", self.u.daughterboard_id()
231
232         # Get the reference pointer to the SpectrumDisplayForm QWidget
233         # Wrap the pointer as a PyQt SIP object
234         #     This can now be manipulated as a PyQt4.QtGui.QWidget
235         self.pysink = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
236
237         self.main_win = main_window(self.pysink, self)
238
239         self.main_win.set_frequency(self._freq)
240         self.main_win.set_gain(self._gain)
241         self.main_win.set_bandwidth(self._bandwidth)
242         self.main_win.set_amplifier(self._amp_value)
243
244         self.main_win.show()
245
246
247     def save_to_file(self, name):
248         self.lock()
249
250         # Add file sink to save data
251         self.file_sink = gr.file_sink(gr.sizeof_gr_complex, name)
252         self.connect(self.amp, self.file_sink)
253
254         self.unlock()
255
256     def set_gain(self, gain):
257         self._gain = gain
258         self.u.set_gain(self._gain)
259
260     def set_frequency(self, freq):
261         self._freq = freq
262         r = self.u.set_center_freq(freq)
263
264         try:
265             self.snk.set_frequency_range(self._freq, self._bandwidth)
266         except:
267             pass
268
269     def set_bandwidth(self, bw):
270         self._bandwidth = bw
271         self._decim = int(self._adc_rate / self._bandwidth)
272         self.u.set_decim(self._decim)
273
274         try:
275             self.snk.set_frequency_range(self._freq, self._bandwidth)
276         except:
277             pass
278
279     def set_amplifier_gain(self, amp):
280         self._amp_value = amp
281         self.amp.set_k(self._amp_value)
282
283     def set_dc_gain(self, gain):
284         self.dc.set_taps(gain)
285         
286     def cancel_dc(self, state):
287         self.lock()
288
289         if(state):
290             self.disconnect(self.u, self.amp)
291             self.connect(self.u, (self.dc_sub,0))
292             self.connect(self.u, self.dc, (self.dc_sub,1))
293             self.connect(self.dc_sub, self.amp)
294         else:
295             self.disconnect(self.dc_sub, self.amp)
296             self.disconnect(self.dc, (self.dc_sub,1))
297             self.disconnect(self.u, self.dc)
298             self.disconnect(self.u, (self.dc_sub,0))
299             self.connect(self.u, self.amp)
300
301         self.unlock()
302
303 def main ():
304     tb = my_top_block()
305     tb.start()
306     tb.snk.exec_();
307
308 if __name__ == '__main__':
309     try:
310         main ()
311     except KeyboardInterrupt:
312         pass
313