8236708b360aca7d0cbd0c0ea49efbd4334f3dd2
[debian/gnuradio] / gr-wxgui / src / python / scopesink_gl.py
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 scope_window
26 import common
27 from gnuradio import gr
28 from pubsub import pubsub
29 from constants import *
30
31 ##################################################
32 # Scope sink block (wrapper for old wxgui)
33 ##################################################
34 class _scope_sink_base(gr.hier_block2, common.prop_setter):
35         """!
36         A scope block with a gui window.
37         """
38
39         def __init__(
40                 self,
41                 parent,
42                 title='',
43                 sample_rate=1,
44                 size=scope_window.DEFAULT_WIN_SIZE,
45                 frame_decim=None, #ignore (old wrapper)
46                 v_scale=scope_window.DEFAULT_V_SCALE,
47                 t_scale=None,
48                 num_inputs=1,
49                 ac_couple=False,
50                 xy_mode=False,
51                 frame_rate=scope_window.DEFAULT_FRAME_RATE,
52         ):
53                 if t_scale is None: t_scale = 0.001
54                 #init
55                 gr.hier_block2.__init__(
56                         self,
57                         "scope_sink",
58                         gr.io_signature(num_inputs, num_inputs, self._item_size),
59                         gr.io_signature(0, 0, 0),
60                 )
61                 #scope
62                 msgq = gr.msg_queue(2)
63                 scope = gr.oscope_sink_f(sample_rate, msgq)
64                 #connect
65                 if self._real:
66                         for i in range(num_inputs):
67                                 self.connect((self, i), (scope, i))
68                 else:
69                         for i in range(num_inputs):
70                                 c2f = gr.complex_to_float() 
71                                 self.connect((self, i), c2f)
72                                 self.connect((c2f, 0), (scope, 2*i+0))
73                                 self.connect((c2f, 1), (scope, 2*i+1))
74                         num_inputs *= 2
75                 #controller
76                 self.controller = pubsub()
77                 self.controller.subscribe(SAMPLE_RATE_KEY, scope.set_sample_rate)
78                 self.controller.publish(SAMPLE_RATE_KEY, scope.sample_rate)
79                 def set_trigger_level(level):
80                         if level == '': scope.set_trigger_level_auto()
81                         else: scope.set_trigger_level(level)
82                 self.controller.subscribe(SCOPE_TRIGGER_LEVEL_KEY, set_trigger_level)
83                 def set_trigger_mode(mode):
84                         if mode == 0: mode = gr.gr_TRIG_AUTO
85                         elif mode < 0: mode = gr.gr_TRIG_NEG_SLOPE
86                         elif mode > 0: mode = gr.gr_TRIG_POS_SLOPE
87                         else: return
88                         scope.set_trigger_mode(mode)
89                 self.controller.subscribe(SCOPE_TRIGGER_MODE_KEY, set_trigger_mode)
90                 self.controller.subscribe(SCOPE_TRIGGER_CHANNEL_KEY, scope.set_trigger_channel)
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 = scope_window.scope_window(
97                         parent=parent,
98                         controller=self.controller,
99                         size=size,
100                         title=title,
101                         frame_rate=frame_rate,
102                         num_inputs=num_inputs,
103                         sample_rate_key=SAMPLE_RATE_KEY,
104                         t_scale=t_scale,
105                         v_scale=v_scale,
106                         ac_couple=ac_couple,
107                         xy_mode=xy_mode,
108                         scope_trigger_level_key=SCOPE_TRIGGER_LEVEL_KEY,
109                         scope_trigger_mode_key=SCOPE_TRIGGER_MODE_KEY,
110                         scope_trigger_channel_key=SCOPE_TRIGGER_CHANNEL_KEY,
111                         msg_key=MSG_KEY,
112                 )
113                 #register callbacks from window for external use
114                 for attr in filter(lambda a: a.startswith('set_'), dir(self.win)):
115                         setattr(self, attr, getattr(self.win, attr))
116                 self._register_set_prop(self.controller, SAMPLE_RATE_KEY)
117                 #backwards compadibility
118                 self.win.set_format_line = lambda: setter(self.win, MARKER_KEY, None)
119                 self.win.set_format_dot = lambda: setter(self.win, MARKER_KEY, 2.0)
120                 self.win.set_format_plus =  lambda: setter(self.win, MARKER_KEY, 3.0)
121
122 class scope_sink_f(_scope_sink_base):
123         _item_size = gr.sizeof_float
124         _real = True
125
126 class scope_sink_c(_scope_sink_base):
127         _item_size = gr.sizeof_gr_complex
128         _real = False
129
130 #backwards compadible wrapper (maybe only grc uses this)
131 class constellation_sink(scope_sink_c):
132         def __init__(self, *args, **kwargs):
133                 scope_sink_c.__init__(self, *args, **kwargs)
134                 self.set_scope_xy_mode(True)
135
136 # ----------------------------------------------------------------
137 # Stand-alone test application
138 # ----------------------------------------------------------------
139
140 import wx
141 from gnuradio.wxgui import stdgui2
142
143 class test_top_block (stdgui2.std_top_block):
144     def __init__(self, frame, panel, vbox, argv):
145         stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv)
146
147         if len(argv) > 1:
148             frame_decim = int(argv[1]) 
149         else:
150             frame_decim = 1
151
152         if len(argv) > 2:
153             v_scale = float(argv[2])  # start up at this v_scale value
154         else:
155             v_scale = None  # start up in autorange mode, default
156
157         if len(argv) > 3:
158             t_scale = float(argv[3])  # start up at this t_scale value
159         else:
160             t_scale = .00003  # old behavior
161
162         print "frame decim %s  v_scale %s  t_scale %s" % (frame_decim,v_scale,t_scale)
163             
164         input_rate = 1e6
165
166         # Generate a complex sinusoid
167         self.src0 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 25.1e3, 1e3)
168
169         # We add this throttle block so that this demo doesn't suck down
170         # all the CPU available.  You normally wouldn't use it...
171         self.thr = gr.throttle(gr.sizeof_gr_complex, input_rate)
172
173         scope = scope_sink_c (panel,"Secret Data",sample_rate=input_rate,
174                               frame_decim=frame_decim,
175                               v_scale=v_scale, t_scale=t_scale)
176         vbox.Add (scope.win, 1, wx.EXPAND)
177
178         # Ultimately this will be
179         # self.connect("src0 throttle scope")
180         self.connect(self.src0, self.thr, scope) 
181
182 def main ():
183     app = stdgui2.stdapp (test_top_block, "O'Scope Test App")
184     app.MainLoop ()
185
186 if __name__ == '__main__':
187     main ()