~ubuntu-branches/ubuntu/trusty/gnuradio/trusty

« back to all changes in this revision

Viewing changes to gr-utils/src/python/usrp2_fft.py

  • Committer: Bazaar Package Importer
  • Author(s): Kamal Mostafa
  • Date: 2010-03-13 07:46:01 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100313074601-zjsa893a87bozyh7
Tags: 3.2.2.dfsg-1ubuntu1
* Fix build for Ubuntu lucid (LP: #260406)
  - add binary package dep for libusrp0, libusrp2-0: adduser
  - debian/rules clean: remove pre-built Qt moc files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
#
 
3
# Copyright 2004,2005,2007,2008 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, gru
 
24
from gnuradio import usrp2
 
25
from gnuradio import eng_notation
 
26
from gnuradio.eng_option import eng_option
 
27
from gnuradio.wxgui import stdgui2, fftsink2, waterfallsink2, scopesink2, form, slider
 
28
from optparse import OptionParser
 
29
import wx
 
30
import sys
 
31
import numpy
 
32
 
 
33
class app_top_block(stdgui2.std_top_block):
 
34
    def __init__(self, frame, panel, vbox, argv):
 
35
        stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)
 
36
 
 
37
        self.frame = frame
 
38
        self.panel = panel
 
39
        
 
40
        parser = OptionParser(option_class=eng_option)
 
41
        parser.add_option("-e", "--interface", type="string", default="eth0",
 
42
                          help="select Ethernet interface, default is eth0")
 
43
        parser.add_option("-m", "--mac-addr", type="string", default="",
 
44
                          help="select USRP by MAC address, default is auto-select")
 
45
        #parser.add_option("-A", "--antenna", default=None,
 
46
        #                  help="select Rx Antenna (only on RFX-series boards)")
 
47
        parser.add_option("-d", "--decim", type="int", default=16,
 
48
                          help="set fgpa decimation rate to DECIM [default=%default]")
 
49
        parser.add_option("-f", "--freq", type="eng_float", default=None,
 
50
                          help="set frequency to FREQ", metavar="FREQ")
 
51
        parser.add_option("-g", "--gain", type="eng_float", default=None,
 
52
                          help="set gain in dB (default is midpoint)")
 
53
        parser.add_option("-W", "--waterfall", action="store_true", default=False,
 
54
                          help="Enable waterfall display")
 
55
        parser.add_option("-S", "--oscilloscope", action="store_true", default=False,
 
56
                          help="Enable oscilloscope display")
 
57
        parser.add_option("", "--avg-alpha", type="eng_float", default=1e-1,
 
58
                          help="Set fftsink averaging factor, default=[%default]")
 
59
        parser.add_option("", "--ref-scale", type="eng_float", default=1.0,
 
60
                          help="Set dBFS=0dB input value, default=[%default]")
 
61
        parser.add_option("--fft-size", type="int", default=1024,
 
62
                          help="Set number of FFT bins [default=%default]")
 
63
        (options, args) = parser.parse_args()
 
64
        if len(args) != 0:
 
65
            parser.print_help()
 
66
            sys.exit(1)
 
67
        self.options = options
 
68
        self.show_debug_info = True
 
69
        
 
70
        self.u = usrp2.source_32fc(options.interface, options.mac_addr)
 
71
        self.u.set_decim(options.decim)
 
72
        
 
73
        input_rate = self.u.adc_rate() / self.u.decim()
 
74
        
 
75
        if options.waterfall:
 
76
            self.scope = \
 
77
              waterfallsink2.waterfall_sink_c (panel, fft_size=1024, sample_rate=input_rate)
 
78
        elif options.oscilloscope:
 
79
            self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate)
 
80
        else:
 
81
            self.scope = fftsink2.fft_sink_c (panel,
 
82
                                              fft_size=options.fft_size,
 
83
                                              sample_rate=input_rate, 
 
84
                                              ref_scale=options.ref_scale,
 
85
                                              ref_level=20.0,
 
86
                                              y_divs = 12,
 
87
                                              avg_alpha=options.avg_alpha)
 
88
 
 
89
        self.connect(self.u, self.scope)
 
90
 
 
91
        self._build_gui(vbox)
 
92
        self._setup_events()
 
93
        
 
94
        # set initial values
 
95
 
 
96
        if options.gain is None:
 
97
            # if no gain was specified, use the mid-point in dB
 
98
            g = self.u.gain_range()
 
99
            options.gain = float(g[0]+g[1])/2
 
100
 
 
101
        if options.freq is None:
 
102
            # if no freq was specified, use the mid-point
 
103
            r = self.u.freq_range()
 
104
            options.freq = float(r[0]+r[1])/2
 
105
            
 
106
        self.set_gain(options.gain)
 
107
 
 
108
        #if options.antenna is not None:
 
109
        #    print "Selecting antenna %s" % (options.antenna,)
 
110
        #    self.subdev.select_rx_antenna(options.antenna)
 
111
 
 
112
        if self.show_debug_info:
 
113
            self.myform['decim'].set_value(self.u.decim())
 
114
            self.myform['fs@gbe'].set_value(input_rate)
 
115
            self.myform['dbname'].set_value("0x%04X" % (self.u.daughterboard_id(),)) # FIXME: add text name
 
116
            self.myform['baseband'].set_value(0)
 
117
            self.myform['ddc'].set_value(0)
 
118
 
 
119
        if not(self.set_freq(options.freq)):
 
120
            self._set_status_msg("Failed to set initial frequency")
 
121
 
 
122
    def _set_status_msg(self, msg):
 
123
        self.frame.GetStatusBar().SetStatusText(msg, 0)
 
124
 
 
125
    def _build_gui(self, vbox):
 
126
 
 
127
        def _form_set_freq(kv):
 
128
            return self.set_freq(kv['freq'])
 
129
            
 
130
        vbox.Add(self.scope.win, 10, wx.EXPAND)
 
131
        
 
132
        # add control area at the bottom
 
133
        self.myform = myform = form.form()
 
134
        hbox = wx.BoxSizer(wx.HORIZONTAL)
 
135
        hbox.Add((5,0), 0, 0)
 
136
        myform['freq'] = form.float_field(
 
137
            parent=self.panel, sizer=hbox, label="Center freq", weight=1,
 
138
            callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))
 
139
 
 
140
        hbox.Add((5,0), 0, 0)
 
141
        g = self.u.gain_range()
 
142
 
 
143
        # some configurations don't have gain control
 
144
        if g[1] > g[0]:
 
145
            myform['gain'] = form.slider_field(parent=self.panel, sizer=hbox, label="Gain",
 
146
                                           weight=3,
 
147
                                           min=int(g[0]), max=int(g[1]),
 
148
                                           callback=self.set_gain)
 
149
 
 
150
        hbox.Add((5,0), 0, 0)
 
151
        vbox.Add(hbox, 0, wx.EXPAND)
 
152
 
 
153
        self._build_subpanel(vbox)
 
154
 
 
155
    def _build_subpanel(self, vbox_arg):
 
156
        # build a secondary information panel (sometimes hidden)
 
157
 
 
158
        # FIXME figure out how to have this be a subpanel that is always
 
159
        # created, but has its visibility controlled by foo.Show(True/False)
 
160
        
 
161
        def _form_set_decim(kv):
 
162
            return self.set_decim(kv['decim'])
 
163
 
 
164
        if not(self.show_debug_info):
 
165
            return
 
166
 
 
167
        panel = self.panel
 
168
        vbox = vbox_arg
 
169
        myform = self.myform
 
170
 
 
171
        #panel = wx.Panel(self.panel, -1)
 
172
        #vbox = wx.BoxSizer(wx.VERTICAL)
 
173
 
 
174
        hbox = wx.BoxSizer(wx.HORIZONTAL)
 
175
        hbox.Add((5,0), 0)
 
176
 
 
177
        myform['decim'] = form.int_field(
 
178
            parent=panel, sizer=hbox, label="Decim",
 
179
            callback=myform.check_input_and_call(_form_set_decim, self._set_status_msg))
 
180
 
 
181
        hbox.Add((5,0), 1)
 
182
        myform['fs@gbe'] = form.static_float_field(
 
183
            parent=panel, sizer=hbox, label="Fs@GbE")
 
184
 
 
185
        hbox.Add((5,0), 1)
 
186
        myform['dbname'] = form.static_text_field(
 
187
            parent=panel, sizer=hbox)
 
188
 
 
189
        hbox.Add((5,0), 1)
 
190
        myform['baseband'] = form.static_float_field(
 
191
            parent=panel, sizer=hbox, label="Analog BB")
 
192
 
 
193
        hbox.Add((5,0), 1)
 
194
        myform['ddc'] = form.static_float_field(
 
195
            parent=panel, sizer=hbox, label="DDC")
 
196
 
 
197
        hbox.Add((5,0), 0)
 
198
        vbox.Add(hbox, 0, wx.EXPAND)
 
199
 
 
200
        
 
201
    def set_freq(self, target_freq):
 
202
        """
 
203
        Set the center frequency we're interested in.
 
204
 
 
205
        @param target_freq: frequency in Hz
 
206
        @rypte: bool
 
207
 
 
208
        Tuning is a two step process.  First we ask the front-end to
 
209
        tune as close to the desired frequency as it can.  Then we use
 
210
        the result of that operation and our target_frequency to
 
211
        determine the value for the digital down converter.
 
212
        """
 
213
        r = self.u.set_center_freq(target_freq)
 
214
        
 
215
        if r:
 
216
            self.myform['freq'].set_value(target_freq)     # update displayed value
 
217
            if self.show_debug_info:
 
218
                self.myform['baseband'].set_value(r.baseband_freq)
 
219
                self.myform['ddc'].set_value(r.dxc_freq)
 
220
            if not self.options.oscilloscope:
 
221
                self.scope.win.set_baseband_freq(target_freq)
 
222
            return True
 
223
 
 
224
        return False
 
225
 
 
226
    def set_gain(self, gain):
 
227
        if self.myform.has_key('gain'):
 
228
            self.myform['gain'].set_value(gain)     # update displayed value
 
229
        self.u.set_gain(gain)
 
230
 
 
231
    def set_decim(self, decim):
 
232
        ok = self.u.set_decim(decim)
 
233
        if not ok:
 
234
            print "set_decim failed"
 
235
        input_rate = self.u.adc_rate() / self.u.decim()
 
236
        self.scope.set_sample_rate(input_rate)
 
237
        if self.show_debug_info:  # update displayed values
 
238
            self.myform['decim'].set_value(self.u.decim())
 
239
            self.myform['fs@gbe'].set_value(input_rate)
 
240
        return ok
 
241
 
 
242
    def _setup_events(self):
 
243
        if not self.options.waterfall and not self.options.oscilloscope:
 
244
            self.scope.win.Bind(wx.EVT_LEFT_DCLICK, self.evt_left_dclick)
 
245
            
 
246
    def evt_left_dclick(self, event):
 
247
        (ux, uy) = self.scope.win.GetXY(event)
 
248
        if event.CmdDown():
 
249
            # Re-center on maximum power
 
250
            points = self.scope.win._points
 
251
            if self.scope.win.peak_hold:
 
252
                if self.scope.win.peak_vals is not None:
 
253
                    ind = numpy.argmax(self.scope.win.peak_vals)
 
254
                else:
 
255
                    ind = int(points.shape()[0]/2)
 
256
            else:
 
257
                ind = numpy.argmax(points[:,1])
 
258
            (freq, pwr) = points[ind]
 
259
            target_freq = freq/self.scope.win._scale_factor
 
260
            print ind, freq, pwr
 
261
            self.set_freq(target_freq)            
 
262
        else:
 
263
            # Re-center on clicked frequency
 
264
            target_freq = ux/self.scope.win._scale_factor
 
265
            self.set_freq(target_freq)
 
266
            
 
267
        
 
268
def main ():
 
269
    app = stdgui2.stdapp(app_top_block, "USRP2 FFT", nstatus=1)
 
270
    app.MainLoop()
 
271
 
 
272
if __name__ == '__main__':
 
273
    main ()