Revision b3104784

b/gr-wxgui/src/python/Makefile.am
37 37
	scopesink.py			\
38 38
	waterfallsink.py		\
39 39
	slider.py			\
40
	stdgui.py			
40
	stdgui.py			\
41
	numbersink.py		
b/gr-wxgui/src/python/numbersink.py
1
#!/usr/bin/env python
2
#
3
# Copyright 2003,2004,2005,2006 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 2, 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., 59 Temple Place - Suite 330,
20
# Boston, MA 02111-1307, USA.
21
# 
22

23
from gnuradio import gr, gru, window
24
from gnuradio.wxgui import stdgui
25
import wx
26
#from wx import StaticText
27
import gnuradio.wxgui.plot as plot
28
import Numeric
29
import threading
30
import math    
31

32
default_numbersink_size = (640,240)
33
default_number_rate = gr.prefs().get_long('wxgui', 'number_rate', 15)
34

35
class number_sink_base(object):
36
    def __init__(self, input_is_real=False, unit='',base_value=0, minval=-100.0,maxval=100.0,factor=1.0,decimal_places=10, ref_level=50,
37
                 sample_rate=1, 
38
                 number_rate=default_number_rate,
39
                 average=False, avg_alpha=None, label='', peak_hold=False):
40

41
        # initialize common attributes
42
        self.unit=unit
43
        self.base_value = base_value
44
        self.minval=minval
45
        self.maxval=maxval
46
        self.factor=factor
47
        self.y_divs = 8
48
        self.decimal_places=decimal_places
49
        self.ref_level = ref_level
50
        self.sample_rate = sample_rate
51
        number_size=1
52
        self.number_size = number_size
53
        self.number_rate = number_rate
54
        self.average = average
55
        if avg_alpha is None:
56
            self.avg_alpha = 2.0 / number_rate
57
        else:
58
            self.avg_alpha = avg_alpha
59
        self.label = label
60
        self.peak_hold = peak_hold
61
        self.show_gauge = True
62
        self.input_is_real = input_is_real
63
        self.msgq = gr.msg_queue(2)         # queue that holds a maximum of 2 messages
64

65
    def set_decimal_places(self, decimal_places):
66
        self.decimal_places = decimal_places
67

68
    def set_ref_level(self, ref_level):
69
        self.ref_level = ref_level
70

71
    def print_current_value(self, comment):
72
        print comment,self.win.current_value
73

74
    def set_average(self, average):
75
        self.average = average
76
        if average:
77
            self.avg.set_taps(self.avg_alpha)
78
            self.set_peak_hold(False)
79
        else:
80
            self.avg.set_taps(1.0)
81

82
    def set_peak_hold(self, enable):
83
        self.peak_hold = enable
84
        if enable:
85
            self.set_average(False)
86
        self.win.set_peak_hold(enable)
87

88
    def set_show_gauge(self, enable):
89
        self.show_gauge = enable
90
        self.win.set_show_gauge(enable)
91

92
    def set_avg_alpha(self, avg_alpha):
93
        self.avg_alpha = avg_alpha
94

95
    def set_base_value(self, base_value):
96
        self.base_value = base_value
97
        
98

99
class number_sink_f(gr.hier_block, number_sink_base):
100
    def __init__(self, fg, parent, unit='',base_value=0,minval=-100.0,maxval=100.0,factor=1.0,
101
                 decimal_places=10, ref_level=50, sample_rate=1, #number_size=512,
102
                 number_rate=default_number_rate, average=False, avg_alpha=None,
103
                 label='', size=default_numbersink_size, peak_hold=False):
104

105
        number_sink_base.__init__(self, unit=unit, input_is_real=True, base_value=base_value,
106
                               minval=minval,maxval=maxval,factor=factor,
107
                               decimal_places=decimal_places, ref_level=ref_level,
108
                               sample_rate=sample_rate, #number_size=number_size,
109
                               number_rate=number_rate,
110
                               average=average, avg_alpha=avg_alpha, label=label,
111
                               peak_hold=peak_hold)
112
         
113
        number_size=1                      
114
        #s2p = gr.stream_to_vector(gr.sizeof_float, number_size)
115
        one_in_n = gr.keep_one_in_n(gr.sizeof_float,
116
                                    max(1, int(sample_rate/number_rate)))
117

118
            
119
        #c2mag = gr.complex_to_mag(number_size)
120
        self.avg = gr.single_pole_iir_filter_ff(1.0, number_size)
121

122
        # FIXME  We need to add 3dB to all bins but the DC bin
123
        #log = gr.nlog10_ff(20, number_size,
124
        #                   -20*math.log10(number_size)-10*math.log10(power/number_size))
125
        sink = gr.message_sink(gr.sizeof_float , self.msgq, True)
126

127
        #fg.connect (s2p, one_in_n, fft, c2mag, self.avg, log, sink)
128
        fg.connect(self.avg,one_in_n,sink)
129
        gr.hier_block.__init__(self, fg, self.avg, sink)
130
        self.win = number_window(self, parent, size=size,label=label)
131
        self.set_average(self.average)
132

133

134
class number_sink_c(gr.hier_block, number_sink_base):
135
    def __init__(self, fg, parent, unit='',base_value=0,minval=-100.0,maxval=100.0,factor=1.0,
136
                 decimal_places=10, ref_level=50, sample_rate=1, #number_size=512,
137
                 number_rate=default_number_rate, average=False, avg_alpha=None,
138
                 label='', size=default_numbersink_size, peak_hold=False):
139

140
        number_sink_base.__init__(self, unit=unit, input_is_real=False, base_value=base_value,factor=factor,
141
                               minval=minval,maxval=maxval,decimal_places=decimal_places, ref_level=ref_level,
142
                               sample_rate=sample_rate, #number_size=number_size,
143
                               number_rate=number_rate,
144
                               average=average, avg_alpha=avg_alpha, label=label,
145
                               peak_hold=peak_hold)
146

147
        number_size=1                      
148
        one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex,
149
                                    max(1, int(sample_rate/number_rate)))
150

151
            
152
        #c2mag = gr.complex_to_mag(number_size)
153
        self.avg = gr.single_pole_iir_filter_cc(1.0, number_size)
154

155
        # FIXME  We need to add 3dB to all bins but the DC bin
156
        #log = gr.nlog10_ff(20, number_size,
157
        #                   -20*math.log10(number_size)-10*math.log10(power/number_size))
158
        sink = gr.message_sink(gr.sizeof_gr_complex , self.msgq, True)
159

160
        #fg.connect (s2p, one_in_n, fft, c2mag, self.avg, log, sink)
161
        fg.connect(self.avg,one_in_n,sink)
162
        gr.hier_block.__init__(self, fg, self.avg, sink)
163
        self.win = number_window(self, parent, size=size,label=label)
164
        self.set_average(self.average)
165

166

167
# ------------------------------------------------------------------------
168

169
myDATA_EVENT = wx.NewEventType()
170
EVT_DATA_EVENT = wx.PyEventBinder (myDATA_EVENT, 0)
171

172

173
class DataEvent(wx.PyEvent):
174
    def __init__(self, data):
175
        wx.PyEvent.__init__(self)
176
        self.SetEventType (myDATA_EVENT)
177
        self.data = data
178

179
    def Clone (self): 
180
        self.__class__ (self.GetId())
181

182

183
class input_watcher (threading.Thread):
184
    def __init__ (self, msgq, number_size, event_receiver, **kwds):
185
        threading.Thread.__init__ (self, **kwds)
186
        self.setDaemon (1)
187
        self.msgq = msgq
188
        self.number_size = number_size
189
        self.event_receiver = event_receiver
190
        self.keep_running = True
191
        self.start ()
192

193
    def run (self):
194
        while (self.keep_running):
195
            msg = self.msgq.delete_head()  # blocking read of message queue
196
            itemsize = int(msg.arg1())
197
            nitems = int(msg.arg2())
198

199
            s = msg.to_string()            # get the body of the msg as a string
200

201
            # There may be more than one number in the message.
202
            # If so, we take only the last one
203
            if nitems > 1:
204
                start = itemsize * (nitems - 1)
205
                s = s[start:start+itemsize]
206

207
            complex_data = Numeric.fromstring (s, Numeric.Float32)
208
            de = DataEvent (complex_data)
209
            wx.PostEvent (self.event_receiver, de)
210
            del de
211
    
212
#========================================================================================
213
class static_text_window (wx.StaticText): #plot.PlotCanvas):
214
    def __init__ (self, parent, numbersink,id = -1,label="number",
215
                  pos = wx.DefaultPosition, size = wx.DefaultSize,
216
                  style = wx.DEFAULT_FRAME_STYLE, name = ""):
217
        #plot.PlotCanvas.__init__ (self, parent, id, pos, size, style, name)
218
        wx.StaticText.__init__(self, parent, id, label, pos, size, style, name)
219
        #self.static_text=wx.StaticText( parent, id, label, pos, (size[0]/2,size[1]/2), style, name)
220
        #gauge_style = wx.GA_HORIZONTAL
221
        #self.gauge=wx.Gauge( parent, id, range=1000, pos=(pos[0],pos[1]+size[1]/2),size=(size[0]/2,size[1]/2), style=gauge_style,  name = "gauge")
222
        #wx.BoxSizer.__init__ (self,wx.VERTICAL)
223
        #self.Add (self.static_text, 0, wx.EXPAND)
224
        #self.Add (self.gauge, 1, wx.EXPAND)
225
        self.parent=parent
226
        self.label=label
227
        #self.y_range = None
228
        self.numbersink = numbersink
229
        self.peak_hold = False
230
        self.peak_vals = None
231

232
        #self.SetEnableGrid (True)
233
        # self.SetEnableZoom (True)
234
        # self.SetBackgroundColour ('black')
235
        
236
        self.build_popup_menu()
237
        
238
        #EVT_DATA_EVENT (self, self.set_data)
239
        #wx.EVT_CLOSE (self, self.on_close_window)
240
        #self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
241
        self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
242

243
        #self.input_watcher = input_watcher(numbersink.msgq, numbersink.number_size, self)
244

245

246
    def on_close_window (self, event):
247
        print "number_window:on_close_window"
248
        self.keep_running = False
249

250

251
    def set_peak_hold(self, enable):
252
        self.peak_hold = enable
253
        self.peak_vals = None
254

255
    def update_y_range (self):
256
        ymax = self.numbersink.ref_level
257
        ymin = self.numbersink.ref_level - self.numbersink.decimal_places * self.numbersink.y_divs
258
        self.y_range = self._axisInterval ('min', ymin, ymax)
259

260
    def on_average(self, evt):
261
        # print "on_average"
262
        self.numbersink.set_average(evt.IsChecked())
263

264
    def on_peak_hold(self, evt):
265
        # print "on_peak_hold"
266
        self.numbersink.set_peak_hold(evt.IsChecked())
267

268
    def on_show_gauge(self, evt):
269
        # print "on_show_gauge"
270
        #if evt.IsChecked():
271
        self.numbersink.set_show_gauge(evt.IsChecked())
272
        print evt.IsChecked()
273
        #  print "show gauge"
274
        #else:
275
        #  self.parent.gauge.Hide()
276
        #  print "hide gauge"
277

278
    def on_incr_ref_level(self, evt):
279
        # print "on_incr_ref_level"
280
        self.numbersink.set_ref_level(self.numbersink.ref_level
281
                                   + self.numbersink.decimal_places)
282

283
    def on_decr_ref_level(self, evt):
284
        # print "on_decr_ref_level"
285
        self.numbersink.set_ref_level(self.numbersink.ref_level
286
                                   - self.numbersink.decimal_places)
287

288
    def on_incr_decimal_places(self, evt):
289
        # print "on_incr_decimal_places"
290
        self.numbersink.set_decimal_places(self.numbersink.decimal_places+1) #next_up(self.numbersink.decimal_places, (1,2,5,10,20)))
291

292
    def on_decr_decimal_places(self, evt):
293
        # print "on_decr_decimal_places"
294
        self.numbersink.set_decimal_places(max(self.numbersink.decimal_places-1,0)) #next_down(self.numbersink.decimal_places, (1,2,5,10,20)))
295

296
    def on_decimal_places(self, evt):
297
        # print "on_decimal_places"
298
        Id = evt.GetId()
299
        if Id == self.id_decimal_places_0:
300
            self.numbersink.set_decimal_places(0)
301
        elif Id == self.id_decimal_places_1:
302
            self.numbersink.set_decimal_places(1)
303
        elif Id == self.id_decimal_places_2:
304
            self.numbersink.set_decimal_places(2)
305
        elif Id == self.id_decimal_places_3:
306
            self.numbersink.set_decimal_places(3)
307
        elif Id == self.id_decimal_places_6:
308
            self.numbersink.set_decimal_places(6)
309
        elif Id == self.id_decimal_places_9:
310
            self.numbersink.set_decimal_places(9)
311

312
        
313
    def on_right_click(self, event):
314
        menu = self.popup_menu
315
        for id, pred in self.checkmarks.items():
316
            item = menu.FindItemById(id)
317
            item.Check(pred())
318
        self.PopupMenu(menu, event.GetPosition())
319

320

321
    def build_popup_menu(self):
322
        #self.id_hide_gauge = wx.NewId()
323
        self.id_show_gauge = wx.NewId()
324
        self.id_incr_ref_level = wx.NewId()
325
        self.id_decr_ref_level = wx.NewId()
326
        self.id_incr_decimal_places = wx.NewId()
327
        self.id_decr_decimal_places = wx.NewId()
328
        self.id_decimal_places_0 = wx.NewId()
329
        self.id_decimal_places_1 = wx.NewId()
330
        self.id_decimal_places_2 = wx.NewId()
331
        self.id_decimal_places_3 = wx.NewId()
332
        self.id_decimal_places_6 = wx.NewId()
333
        self.id_decimal_places_9 = wx.NewId()
334
        self.id_average = wx.NewId()
335
        self.id_peak_hold = wx.NewId()
336

337
        self.Bind(wx.EVT_MENU, self.on_average, id=self.id_average)
338
        self.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold)
339
        #self.Bind(wx.EVT_MENU, self.on_hide_gauge, id=self.id_hide_gauge)
340
        self.Bind(wx.EVT_MENU, self.on_show_gauge, id=self.id_show_gauge)
341
        self.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level)
342
        self.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level)
343
        self.Bind(wx.EVT_MENU, self.on_incr_decimal_places, id=self.id_incr_decimal_places)
344
        self.Bind(wx.EVT_MENU, self.on_decr_decimal_places, id=self.id_decr_decimal_places)
345
        self.Bind(wx.EVT_MENU, self.on_decimal_places, id=self.id_decimal_places_0)
346
        self.Bind(wx.EVT_MENU, self.on_decimal_places, id=self.id_decimal_places_1)
347
        self.Bind(wx.EVT_MENU, self.on_decimal_places, id=self.id_decimal_places_2)
348
        self.Bind(wx.EVT_MENU, self.on_decimal_places, id=self.id_decimal_places_3)
349
        self.Bind(wx.EVT_MENU, self.on_decimal_places, id=self.id_decimal_places_6)
350
        self.Bind(wx.EVT_MENU, self.on_decimal_places, id=self.id_decimal_places_9)
351

352

353
        # make a menu
354
        menu = wx.Menu()
355
        self.popup_menu = menu
356
        menu.AppendCheckItem(self.id_average, "Average")
357
        menu.AppendCheckItem(self.id_peak_hold, "Peak Hold")
358
        #menu.Append(self.id_hide_gauge, "Hide gauge")
359
        menu.AppendCheckItem(self.id_show_gauge, "Show gauge")
360
        menu.Append(self.id_incr_ref_level, "Incr Ref Level")
361
        menu.Append(self.id_decr_ref_level, "Decr Ref Level")
362
        menu.Append(self.id_incr_decimal_places, "Incr decimal places")
363
        menu.Append(self.id_decr_decimal_places, "Decr decimal places")
364
        menu.AppendSeparator()
365
        # we'd use RadioItems for these, but they're not supported on Mac
366
        menu.AppendCheckItem(self.id_decimal_places_0, "0 decimal places")
367
        menu.AppendCheckItem(self.id_decimal_places_1, "1 decimal places")
368
        menu.AppendCheckItem(self.id_decimal_places_2, "2 decimal places")
369
        menu.AppendCheckItem(self.id_decimal_places_3, "3 decimal places")
370
        menu.AppendCheckItem(self.id_decimal_places_6, "6 decimal places")
371
        menu.AppendCheckItem(self.id_decimal_places_9, "9 decimal places")
372

373
        self.checkmarks = {
374
            self.id_average : lambda : self.numbersink.average,
375
            self.id_peak_hold : lambda : self.numbersink.peak_hold,#            self.id_hide_gauge : lambda : self.numbersink.hide_gauge,
376
            self.id_show_gauge : lambda : self.numbersink.show_gauge,
377
            self.id_decimal_places_0 : lambda : self.numbersink.decimal_places == 0,
378
            self.id_decimal_places_1 : lambda : self.numbersink.decimal_places == 1,
379
            self.id_decimal_places_2 : lambda : self.numbersink.decimal_places == 2,
380
            self.id_decimal_places_3 : lambda : self.numbersink.decimal_places == 3,
381
            self.id_decimal_places_6 : lambda : self.numbersink.decimal_places == 6,
382
            self.id_decimal_places_9 : lambda : self.numbersink.decimal_places == 9,
383
            }
384

385

386
def next_up(v, seq):
387
    """
388
    Return the first item in seq that is > v.
389
    """
390
    for s in seq:
391
        if s > v:
392
            return s
393
    return v
394

395
def next_down(v, seq):
396
    """
397
    Return the last item in seq that is < v.
398
    """
399
    rseq = list(seq[:])
400
    rseq.reverse()
401

402
    for s in rseq:
403
        if s < v:
404
            return s
405
    return v
406

407

408
#========================================================================================
409
class number_window (plot.PlotCanvas):
410
    def __init__ (self, numbersink, parent, id = -1,label="number",
411
                  pos = wx.DefaultPosition, size = wx.DefaultSize,
412
                  style = wx.DEFAULT_FRAME_STYLE, name = ""):
413
        plot.PlotCanvas.__init__ (self, parent, id, pos, size, style, name)
414
        #wx.StaticText.__init__(self, parent, id, label, pos, (size[0]/2,size[1]/2), style, name)
415
        #print 'parent',parent
416
        self.static_text=static_text_window( self, numbersink,id, label, pos, (size[0]/2,size[1]/2), style, name)
417
        gauge_style = wx.GA_HORIZONTAL
418
        vbox=wx.BoxSizer(wx.VERTICAL)
419
        vbox.Add (self.static_text, 0, wx.EXPAND)
420
        self.current_value=None
421
        if numbersink.input_is_real:
422
          self.gauge=wx.Gauge( self, id, range=1000, pos=(pos[0],pos[1]+size[1]/2),size=(size[0]/2,size[1]/2), style=gauge_style,  name = "gauge")
423
          vbox.Add (self.gauge, 1, wx.EXPAND)
424
        else:
425
          self.gauge=wx.Gauge( self, id, range=1000, pos=(pos[0],pos[1]+size[1]/3),size=(size[0]/2,size[1]/3), style=gauge_style,  name = "gauge")
426
          #hbox=wx.BoxSizer(wx.HORIZONTAL)
427
          self.gauge_imag=wx.Gauge( self, id, range=1000, pos=(pos[0],pos[1]+size[1]*2/3),size=(size[0]/2,size[1]/3), style=gauge_style,  name = "gauge_imag")
428
          vbox.Add (self.gauge, 1, wx.EXPAND)
429
          vbox.Add (self.gauge_imag, 1, wx.EXPAND)
430
          #vbox.Add (hbox, 1, wx.EXPAND)
431
        self.sizer = vbox
432
        self.SetSizer (self.sizer)
433
        self.SetAutoLayout (True)
434
        self.sizer.Fit (self)
435

436
        self.label=label
437
        #self.y_range = None
438
        self.numbersink = numbersink
439
        self.peak_hold = False
440
        self.peak_vals = None
441

442
        #self.SetEnableGrid (True)
443
        # self.SetEnableZoom (True)
444
        # self.SetBackgroundColour ('black')
445
        
446
        #self.build_popup_menu()
447
        
448
        EVT_DATA_EVENT (self, self.set_data)
449
        wx.EVT_CLOSE (self, self.on_close_window)
450
        #self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
451
        #self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
452

453
        self.input_watcher = input_watcher(numbersink.msgq, numbersink.number_size, self)
454

455

456
    def on_close_window (self, event):
457
        print "number_window:on_close_window"
458
        self.keep_running = False
459

460
    def set_show_gauge(self, enable):
461
        self.show_gauge = enable
462
        if enable:
463
          self.gauge.Show()
464
          if not self.numbersink.input_is_real:
465
            self.gauge_imag.Show()
466
          #print 'show'
467
        else:
468
          self.gauge.Hide()
469
          if not self.numbersink.input_is_real:
470
            self.gauge_imag.Hide()
471
          #print 'hide'
472

473
    def set_data (self, evt):
474
        numbers = evt.data
475
        L = len (numbers)
476

477
        if self.peak_hold:
478
            if self.peak_vals is None:
479
                self.peak_vals = numbers
480
            else:
481
                self.peak_vals = Numeric.maximum(numbers, self.peak_vals)
482
                numbers = self.peak_vals
483

484
        if self.numbersink.input_is_real:
485
            real_value=numbers[0]*self.numbersink.factor + self.numbersink.base_value
486
            imag_value=0.0
487
            self.current_value=real_value
488
        else:
489
            real_value=numbers[0]*self.numbersink.factor + self.numbersink.base_value
490
            imag_value=numbers[1]*self.numbersink.factor + self.numbersink.base_value
491
            self.current_value=complex(real_value,imag_value)
492
        #x = max(abs(self.numbersink.sample_rate), abs(self.numbersink.base_value))
493
        x = max(real_value, imag_value)
494
        if x >= 1e9:
495
            sf = 1e-9
496
            unit_prefix = "G"
497
        elif x >= 1e6:
498
            sf = 1e-6
499
            unit_prefix = "M"
500
        elif x>= 1e3:
501
            sf = 1e-3
502
            unit_prefix = "k"
503
        else :
504
            sf = 1
505
            unit_prefix = ""
506
        #self.update_y_range ()
507
        if self.numbersink.input_is_real:
508
          showtext = "%s: %.*f %s%s" % (self.label, self.numbersink.decimal_places,real_value*sf,unit_prefix,self.numbersink.unit)
509
        else:
510
          showtext = "%s: %.*f,%.*f %s%s" % (self.label, self.numbersink.decimal_places,real_value*sf,
511
                                                       self.numbersink.decimal_places,imag_value*sf,unit_prefix,self.numbersink.unit)
512
        self.static_text.SetLabel(showtext)
513
        #print (int(float((real_value-self.numbersink.base_value)*1000.0/(self.numbersink.maxval-self.numbersink.minval)))+500)
514
        self.gauge.SetValue(int(float((real_value-self.numbersink.base_value)*1000.0/(self.numbersink.maxval-self.numbersink.minval)))+500)
515
        if not self.numbersink.input_is_real:
516
          self.gauge.SetValue(int(float((imag_value-self.numbersink.base_value)*1000.0/(self.numbersink.maxval-self.numbersink.minval)))+500)
517

518
    def set_peak_hold(self, enable):
519
        self.peak_hold = enable
520
        self.peak_vals = None
521

522
    def update_y_range (self):
523
        ymax = self.numbersink.ref_level
524
        ymin = self.numbersink.ref_level - self.numbersink.decimal_places * self.numbersink.y_divs
525
        self.y_range = self._axisInterval ('min', ymin, ymax)
526

527
    def on_average(self, evt):
528
        # print "on_average"
529
        self.numbersink.set_average(evt.IsChecked())
530

531
    def on_peak_hold(self, evt):
532
        # print "on_peak_hold"
533
        self.numbersink.set_peak_hold(evt.IsChecked())
534

535

536

537

538

539

540

541

542

543

544
# ----------------------------------------------------------------
545
#          	      Deprecated interfaces
546
# ----------------------------------------------------------------
547

548
# returns (block, win).
549
#   block requires a single input stream of float
550
#   win is a subclass of wxWindow
551

552
def make_number_sink_f(fg, parent, label, number_size, input_rate, ymin = 0, ymax=50):
553
    
554
    block = number_sink_f(fg, parent, label=label, number_size=number_size, sample_rate=input_rate,
555
                       decimal_places=(ymax - ymin)/8, ref_level=ymax)
556
    return (block, block.win)
557

558
# returns (block, win).
559
#   block requires a single input stream of gr_complex
560
#   win is a subclass of wxWindow
561

562
def make_number_sink_c(fg, parent, label, number_size, input_rate, ymin=0, ymax=50):
563
    block = number_sink_c(fg, parent, label=label, number_size=number_size, sample_rate=input_rate,
564
                       decimal_places=(ymax - ymin)/8, ref_level=ymax)
565
    return (block, block.win)
566

567

568
# ----------------------------------------------------------------
569
# Standalone test app
570
# ----------------------------------------------------------------
571

572
class test_app_flow_graph (stdgui.gui_flow_graph):
573
    def __init__(self, frame, panel, vbox, argv):
574
        stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
575

576
        #number_size = 256
577

578
        # build our flow graph
579
        input_rate = 20.48e3
580

581
        # Generate a complex sinusoid
582
        src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 2e3, 1)
583
        #src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1)
584

585
        # We add these throttle blocks so that this demo doesn't
586
        # suck down all the CPU available.  Normally you wouldn't use these.
587
        thr1 = gr.throttle(gr.sizeof_gr_complex, input_rate)
588

589
        #sink1 = number_sink_c (self, panel, label="Complex Data", number_size=number_size,
590
        #                    sample_rate=input_rate, base_value=100e3,
591
        #                    ref_level=0, decimal_places=3)
592
        #vbox.Add (sink1.win, 1, wx.EXPAND)
593
        #self.connect (src1, thr1, sink1)
594

595
        src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 1)
596
        #src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1)
597
        thr2 = gr.throttle(gr.sizeof_float, input_rate)
598
        sink2 = number_sink_f (self, panel, unit='Hz',label="Real Data", avg_alpha=0.001,#number_size=number_size*2,
599
                            sample_rate=input_rate, base_value=100e3,
600
                            ref_level=0, decimal_places=3)
601
        vbox.Add (sink2.win, 1, wx.EXPAND)
602
        sink3 = number_sink_c (self, panel, unit='V',label="Complex Data", avg_alpha=0.001,#number_size=number_size*2,
603
                            sample_rate=input_rate, base_value=0,
604
                            ref_level=0, decimal_places=3)
605
        vbox.Add (sink3.win, 1, wx.EXPAND)
606
        self.connect (src2, thr2, sink2)
607
        self.connect (src1, thr1, sink3)
608
def main ():
609
    app = stdgui.stdapp (test_app_flow_graph,
610
                         "Number Sink Test App")
611
    app.MainLoop ()
612

613
if __name__ == '__main__':
614
    main ()

Also available in: Unified diff