Statistics
| Branch: | Tag: | Revision:

root / gr-wxgui / src / python / waterfallsink_gl.py @ 36649d4e

History | View | Annotate | Download (5.6 kB)

1
#
2
# Copyright 2008 Free Software Foundation, Inc.
3
#
4
# This file is part of GNU Radio
5
#
6
# GNU Radio is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 3, or (at your option)
9
# any later version.
10
#
11
# GNU Radio is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with GNU Radio; see the file COPYING.  If not, write to
18
# the Free Software Foundation, Inc., 51 Franklin Street,
19
# Boston, MA 02110-1301, USA.
20
#
21
22
##################################################
23
# Imports
24
##################################################
25
import waterfall_window
26
import common
27
from gnuradio import gr, blks2
28
from pubsub import pubsub
29
from constants import *
30
31
##################################################
32
# Waterfall sink block (wrapper for old wxgui)
33
##################################################
34
class _waterfall_sink_base(gr.hier_block2, common.prop_setter):
35
        """!
36
        An fft block with real/complex inputs and a gui window.
37
        """
38
39
        def __init__(
40
                self,
41
                parent,
42
                baseband_freq=0,
43
                y_per_div=None, #ignore (old wrapper)
44
                ref_level=50,
45
                sample_rate=1,
46
                fft_size=512,
47
                fft_rate=waterfall_window.DEFAULT_FRAME_RATE,
48
                average=False,
49
                avg_alpha=None,
50
                title='',
51
                size=waterfall_window.DEFAULT_WIN_SIZE,
52
                ref_scale=2.0,
53
                dynamic_range=80,
54
                num_lines=256,
55
        ):
56
                #ensure avg alpha
57
                if avg_alpha is None: avg_alpha = 2.0/fft_rate
58
                #init
59
                gr.hier_block2.__init__(
60
                        self,
61
                        "waterfall_sink",
62
                        gr.io_signature(1, 1, self._item_size),
63
                        gr.io_signature(0, 0, 0),
64
                )
65
                #blocks
66
                copy = gr.kludge_copy(self._item_size)
67
                fft = self._fft_chain(
68
                        sample_rate=sample_rate,
69
                        fft_size=fft_size,
70
                        frame_rate=fft_rate,
71
                        ref_scale=ref_scale,
72
                        avg_alpha=avg_alpha,
73
                        average=average,
74
                )
75
                msgq = gr.msg_queue(2)
76
                sink = gr.message_sink(gr.sizeof_float*fft_size, msgq, True)
77
                #connect
78
                self.connect(self, copy, fft, sink)
79
                #controller
80
                self.controller = pubsub()
81
                self.controller.subscribe(AVERAGE_KEY, fft.set_average)
82
                self.controller.publish(AVERAGE_KEY, fft.average)
83
                self.controller.subscribe(AVG_ALPHA_KEY, fft.set_avg_alpha)
84
                self.controller.publish(AVG_ALPHA_KEY, fft.avg_alpha)
85
                self.controller.subscribe(SAMPLE_RATE_KEY, fft.set_sample_rate)
86
                self.controller.publish(SAMPLE_RATE_KEY, fft.sample_rate)
87
                self.controller.subscribe(DECIMATION_KEY, fft.set_decimation)
88
                self.controller.publish(DECIMATION_KEY, fft.decimation)
89
                self.controller.subscribe(FRAME_RATE_KEY, fft.set_vec_rate)
90
                self.controller.publish(FRAME_RATE_KEY, fft.frame_rate)
91
                #start input watcher
92
                def setter(p, k, x): # lambdas can't have assignments :(
93
                        p[k] = x
94
                common.input_watcher(msgq, lambda x: setter(self.controller, MSG_KEY, x))
95
                #create window
96
                self.win = waterfall_window.waterfall_window(
97
                        parent=parent,
98
                        controller=self.controller,
99
                        size=size,
100
                        title=title,
101
                        real=self._real,
102
                        fft_size=fft_size,
103
                        num_lines=num_lines,
104
                        baseband_freq=baseband_freq,
105
                        decimation_key=DECIMATION_KEY,
106
                        sample_rate_key=SAMPLE_RATE_KEY,
107
                        frame_rate_key=FRAME_RATE_KEY,
108
                        dynamic_range=dynamic_range,
109
                        ref_level=ref_level,
110
                        average_key=AVERAGE_KEY,
111
                        avg_alpha_key=AVG_ALPHA_KEY,
112
                        msg_key=MSG_KEY,
113
                )
114
                #register callbacks from window for external use
115
                for attr in filter(lambda a: a.startswith('set_'), dir(self.win)):
116
                        setattr(self, attr, getattr(self.win, attr))
117
                self._register_set_prop(self.controller, SAMPLE_RATE_KEY)
118
                self._register_set_prop(self.controller, AVERAGE_KEY)
119
                self._register_set_prop(self.controller, AVG_ALPHA_KEY)
120
121
class waterfall_sink_f(_waterfall_sink_base):
122
        _fft_chain = blks2.logpwrfft_f
123
        _item_size = gr.sizeof_float
124
        _real = True
125
126
class waterfall_sink_c(_waterfall_sink_base):
127
        _fft_chain = blks2.logpwrfft_c
128
        _item_size = gr.sizeof_gr_complex
129
        _real = False
130
131
# ----------------------------------------------------------------
132
# Standalone test app
133
# ----------------------------------------------------------------
134
135
import wx
136
from gnuradio.wxgui import stdgui2
137
138
class test_top_block (stdgui2.std_top_block):
139
    def __init__(self, frame, panel, vbox, argv):
140
        stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv)
141
142
        fft_size = 512
143
144
        # build our flow graph
145
        input_rate = 20.000e3
146
147
        # Generate a complex sinusoid
148
        self.src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 5.75e3, 1000)
149
        #src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1000)
150
151
        # We add these throttle blocks so that this demo doesn't
152
        # suck down all the CPU available.  Normally you wouldn't use these.
153
        self.thr1 = gr.throttle(gr.sizeof_gr_complex, input_rate)
154
155
        sink1 = waterfall_sink_c (panel, title="Complex Data", fft_size=fft_size,
156
                                  sample_rate=input_rate, baseband_freq=100e3)
157
        self.connect(self.src1, self.thr1, sink1)
158
        vbox.Add (sink1.win, 1, wx.EXPAND)
159
160
        # generate a real sinusoid
161
        self.src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 5.75e3, 1000)
162
        self.thr2 = gr.throttle(gr.sizeof_float, input_rate)
163
        sink2 = waterfall_sink_f (panel, title="Real Data", fft_size=fft_size,
164
                                  sample_rate=input_rate, baseband_freq=100e3)
165
        self.connect(self.src2, self.thr2, sink2)
166
        vbox.Add (sink2.win, 1, wx.EXPAND)
167
168
169
def main ():
170
    app = stdgui2.stdapp (test_top_block, "Waterfall Sink Test App")
171
    app.MainLoop ()
172
173
if __name__ == '__main__':
174
    main ()
175