commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r8745 - gnuradio/branches/developers/jblum/gr-wxglgui/


From: jblum
Subject: [Commit-gnuradio] r8745 - gnuradio/branches/developers/jblum/gr-wxglgui/src/python
Date: Sat, 28 Jun 2008 21:13:52 -0600 (MDT)

Author: jblum
Date: 2008-06-28 21:13:51 -0600 (Sat, 28 Jun 2008)
New Revision: 8745

Modified:
   gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
   gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
   gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
Log:
work on scopesink

Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py  
2008-06-29 03:07:54 UTC (rev 8744)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py  
2008-06-29 03:13:51 UTC (rev 8745)
@@ -20,6 +20,8 @@
 # 
 
 import threading
+import numpy
+import math
 import wx
 
 class LabelText(wx.StaticText):        
@@ -52,3 +54,51 @@
 
        def run(self):          
                while self.keep_running: 
self.handle_msg(self.msgq.delete_head())
+
+def get_exp(num):
+       """!
+       Get the exponent of the number in base 10.
+       @param num the floating point number
+       @return the exponent as an integer
+       """
+       return int(math.floor(math.log10(num)))
+
+def get_clean_num(num):
+       """!
+       Get the closest clean number match to num with bases 1, 2, 5.
+       @param num the number
+       @return the closest number
+       """
+       exp = get_exp(num)
+       nums = numpy.array((1, 2, 5, 10))*(10**exp)             
+       return nums[numpy.argmin(numpy.abs(nums - num))]
+
+def get_clean_incr(num):
+       """!
+       Get the next higher clean number with bases 1, 2, 5.
+       @param num the number
+       @return the next higher number
+       """
+       exp = get_exp(num)
+       num = get_clean_num(num)
+       base = int(num/10**exp) 
+       return {
+               1: 2,
+               2: 5,
+               5: 10,
+       }[base]*(10**exp)
+
+def get_clean_decr(num):
+       """!
+       Get the next lower clean number with bases 1, 2, 5.
+       @param num the number
+       @return the next lower number
+       """
+       exp = get_exp(num)
+       num = get_clean_num(num)        
+       base = int(num/10**exp)
+       return {
+               1: .5,
+               2: 1,
+               5: 2,
+       }[base]*(10**exp)

Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py 
2008-06-29 03:07:54 UTC (rev 8744)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py 
2008-06-29 03:13:51 UTC (rev 8745)
@@ -32,7 +32,7 @@
 ##################################################
 # Constants
 ##################################################
-DEFAULT_FFT_RATE = gr.prefs().get_long('wxgui', 'fft_rate', 15)
+DEFAULT_FRAME_RATE = 30
 DEFAULT_WIN_SIZE = (640, 240)
 DIV_LEVELS = (1, 2, 5, 10, 20)
 FFT_PLOT_COLOR_SPEC = (0, 0, 1) 
@@ -202,9 +202,8 @@
                #determine best fitting x_per_div
                if self.real: x_width = self.sample_rate/2.0
                else: x_width = self.sample_rate
-               exp = math.floor(math.log10(x_width/self.x_divs))               
-               x_per_divs = numpy.array((1, 2, 5, 10))*10**exp         
-               x_per_div = x_per_divs[numpy.argmin(numpy.abs(x_per_divs - 
x_width/self.x_divs))]                       
+               x_per_div = common.get_clean_num(x_width/self.x_divs)   
+               exp = common.get_exp(x_per_div) 
                #calculate units and scalar
                if exp >= 9: x_units, scalar = 'GHz', 1e-9
                elif exp >= 6: x_units, scalar = 'MHz', 1e-6
@@ -227,7 +226,7 @@
                self.plotter.set_x_units('Frequency (%s)'%x_units)              
                #update y grid
                
self.plotter.set_y_grid(self.ref_level-self.y_per_div*self.y_divs, 
self.ref_level, self.y_per_div)
-               #update control panel if non-gui changes occured
+               #update control panel
                self.control_panel.update()
                #update the plotter
                self.plotter.update()
@@ -259,15 +258,17 @@
 class fft_block(gr.hier_block2):
        """!
        Create an fft block chain, with real/complex input.
+       The fft stream is written to a message sink.
+       This block provides a callback to set the average on/off.
        """
        
-       def __init__(self, item_size, sample_rate, fft_size, fft_rate, 
ref_scale, avg_alpha):
+       def __init__(self, item_size, sample_rate, fft_size, frame_rate, 
ref_scale, avg_alpha):
                """!
                Create an fft block.
                Write the samples to a message sink.
                Provide access to the msg queue and setting the filter.
                @param item_size the input size complex or float
-               @param sample_rate, fft_size, fft_rate, ref_scale, avg_alpha 
the fft parameters
+               @param sample_rate, fft_size, frame_rate, ref_scale, avg_alpha 
the fft parameters
                """
                self._avg_alpha = avg_alpha
                #init
@@ -279,7 +280,7 @@
                )
                #create blocks
                s2p = gr.stream_to_vector(item_size, fft_size)          
-               one_in_n = gr.keep_one_in_n(item_size * fft_size, max(1, 
int(sample_rate/fft_size/fft_rate)))           
+               one_in_n = gr.keep_one_in_n(item_size * fft_size, max(1, 
int(sample_rate/fft_size/frame_rate)))         
                #create fft
                fft_window = window.blackmanharris(fft_size)
                fft = {
@@ -316,9 +317,7 @@
 ##################################################     
 class _fft_sink_base(gr.hier_block2):
        """!
-       An fft block with real/complex inputs.
-       The fft stream is written to a message sink.
-       This block provides a callback to set the average on/off.
+       An fft block with real/complex inputs and a gui window.
        """
        
        def __init__(
@@ -331,7 +330,7 @@
                ref_level=50,
                sample_rate=1, 
                fft_size=512,
-               fft_rate=DEFAULT_FFT_RATE,
+               frame_rate=DEFAULT_FRAME_RATE,
                average=False, 
                avg_alpha=None, 
                title='', 
@@ -340,7 +339,7 @@
        ): 
                self.real = self.item_size == gr.sizeof_float
                #ensure avg alpha
-               if avg_alpha is None: avg_alpha = 2.0/fft_rate
+               if avg_alpha is None: avg_alpha = 2.0/frame_rate
                #init
                gr.hier_block2.__init__(
                        self, 
@@ -354,7 +353,7 @@
                        item_size=self.item_size,
                        sample_rate=sample_rate, 
                        fft_size=fft_size, 
-                       fft_rate=fft_rate, 
+                       frame_rate=frame_rate, 
                        ref_scale=ref_scale, 
                        avg_alpha=avg_alpha,
                )
@@ -410,64 +409,3 @@
 
 class fft_sink_f(_fft_sink_base): item_size = gr.sizeof_float
 class fft_sink_c(_fft_sink_base): item_size = gr.sizeof_gr_complex
-
-# ----------------------------------------------------------------
-# Standalone test app
-# ----------------------------------------------------------------
-
-class test_app_block (gr.top_block):
-       def __init__(self, frame, vbox):
-               gr.top_block.__init__(self)
-               fft_size = 256
-
-               # build our flow graph
-               input_rate = 20.48e3
-
-               # Generate a complex sinusoid
-               #src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 2e3, 1)
-               src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1)
-
-               # We add these throttle blocks so that this demo doesn't
-               # suck down all the CPU available.  Normally you wouldn't use 
these.
-               thr1 = gr.throttle(gr.sizeof_gr_complex, input_rate)
-
-               sink1 = fft_sink_c (frame, title="Complex Data", 
fft_size=fft_size,
-                                                       sample_rate=input_rate, 
baseband_freq=100e3,
-                                                       ref_level=0, 
y_per_div=20, y_divs=10)
-               vbox.Add (sink1.win, 1, wx.EXPAND)
-
-               self.connect(src1, thr1, sink1)
-
-               #src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 1)
-               src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1)
-               thr2 = gr.throttle(gr.sizeof_float, input_rate)
-               sink2 = fft_sink_f (frame, title="Real Data", 
fft_size=fft_size*2,
-                                                       sample_rate=input_rate, 
baseband_freq=100e3,
-                                                       ref_level=0, 
y_per_div=20, y_divs=10)
-               vbox.Add (sink2.win, 1, wx.EXPAND)
-
-               self.connect(src2, thr2, sink2)
-               self.start()
-
-def main ():
-       app = wx.PySimpleApp()
-       frame = wx.Frame(None, -1, 'Demo', wx.DefaultPosition)
-       vbox = wx.BoxSizer(wx.VERTICAL)
-       test_app_block(frame, vbox)
-       frame.SetSizerAndFit(vbox)
-       frame.SetSize(wx.Size(800, 500))
-       frame.Show()
-       app.MainLoop()
-
-if __name__ == '__main__':
-       main ()
-       #tb = gr.top_block()
-       #src1 = gr.sig_source_f (23e3, gr.GR_CONST_WAVE, 5.75e3, 1)
-       #def handle_samples(samp):
-       #       print len(samp)
-       #fft = fft_block(4, 23e3, 256, 1., 1., 1.)
-       #tb.connect(src1, fft)
-       #tb.start()
-       #input_watcher(fft.msgq, handle_samples)
-       #raw_input()
-

Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py       
2008-06-29 03:07:54 UTC (rev 8744)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py       
2008-06-29 03:13:51 UTC (rev 8745)
@@ -32,20 +32,25 @@
 ##################################################
 # Constants
 ##################################################
-DEFAULT_FRAME_DECIM = gr.prefs().get_long('wxgui', 'frame_decim', 15)
 DEFAULT_WIN_SIZE = (640, 240)
 DEFAULT_V_SCALE = 1000
 TRIGGER_MODES = (
-       ('Automatic', gr.gr_TRIG_AUTO), 
-       ('Negative', gr.gr_TRIG_NEG_SLOPE),     
-       ('Positive', gr.gr_TRIG_POS_SLOPE),     
+       ('Auto', gr.gr_TRIG_AUTO),      
+       ('Neg', gr.gr_TRIG_NEG_SLOPE),  
+       ('Pos', gr.gr_TRIG_POS_SLOPE),  
 )
 TRIGGER_LEVELS = (
-       ('Automatic', None),
+       ('Auto', None),
        ('Low', -0.5),
-       ('Medium', 0.0),
+       ('Med', 0.0),
        ('High', 0.5),
 )
+CHANNEL_COLOR_SPECS = (
+       (0, 0, 1),
+       (0, 1, 0),
+       (1, 0, 0),
+       (1, 1, 0),
+)
 
 ##################################################
 # Scope window control panel
@@ -66,7 +71,6 @@
                #begin control box
                control_box.AddStretchSpacer()
                control_box.Add(common.LabelText(self, 'Select Channel'), 0, 
wx.ALIGN_CENTER)
-               control_box.AddSpacer(2)                                
                #channel and trigger box
                channel_trigger_box = wx.BoxSizer(wx.HORIZONTAL)
                control_box.Add(channel_trigger_box, 0, wx.EXPAND)              
@@ -82,66 +86,61 @@
                #offset slider
                control_box.AddStretchSpacer()
                control_box.Add(common.LabelText(self, 'Channel Offset'), 0, 
wx.ALIGN_CENTER)
-               control_box.AddSpacer(2)
                self.offset_slider = wx.Slider(self, -1, style=wx.SL_HORIZONTAL)
                control_box.Add(self.offset_slider, 0, wx.EXPAND)               
                
-               #trigger mode
+               #trigger menu
                control_box.AddStretchSpacer()
-               control_box.Add(common.LabelText(self, 'Trigger Mode'), 0, 
wx.ALIGN_CENTER)
-               control_box.AddSpacer(2)
+               control_box.Add(common.LabelText(self, 'Trigger Menu'), 0, 
wx.ALIGN_CENTER)
+               #trigger mode           
+               hbox = wx.BoxSizer(wx.HORIZONTAL)
+               control_box.Add(hbox, 1, wx.ALIGN_LEFT)         
+               hbox.Add(common.LabelText(self, ' Mode: '), 0, 
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)                
                self.trigger_mode_chooser = wx.Choice(self, -1, choices=[tm[0] 
for tm in TRIGGER_MODES])
                self.trigger_mode_chooser.Bind(wx.EVT_CHOICE, self._on_chooser)
-               control_box.Add(self.trigger_mode_chooser, 0, wx.ALIGN_CENTER)
-               
+               hbox.Add(self.trigger_mode_chooser, 0, wx.ALIGN_CENTER_VERTICAL 
| wx.ALIGN_LEFT)                
                #trigger level
-               control_box.AddStretchSpacer()
-               control_box.Add(common.LabelText(self, 'Trigger Level'), 0, 
wx.ALIGN_CENTER)
-               control_box.AddSpacer(2)
+               hbox = wx.BoxSizer(wx.HORIZONTAL)
+               control_box.Add(hbox, 1, wx.ALIGN_LEFT) 
+               hbox.Add(common.LabelText(self, ' Level: '), 0, 
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
                self.trigger_level_chooser = wx.Choice(self, -1, choices=[tl[0] 
for tl in TRIGGER_LEVELS])
                self.trigger_level_chooser.Bind(wx.EVT_CHOICE, self._on_chooser)
-               control_box.Add(self.trigger_level_chooser, 0, wx.ALIGN_CENTER) 
        
+               hbox.Add(self.trigger_level_chooser, 0, 
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
                
-               #setup axis boxes
-               axis_box = wx.BoxSizer(wx.HORIZONTAL)   
-               x_axis_box = wx.BoxSizer(wx.VERTICAL)
-               y_axis_box = wx.BoxSizer(wx.VERTICAL)
-               axis_box.Add(x_axis_box, 1, wx.EXPAND)
-               axis_box.Add(y_axis_box, 1, wx.EXPAND)
+               #setup axes menu
                control_box.AddStretchSpacer()
-               control_box.Add(axis_box, 0, wx.ALIGN_CENTER)
-               
+               control_box.Add(common.LabelText(self, 'Axes Menu'), 0, 
wx.ALIGN_CENTER)
                #x axis
-               x_axis_box.Add(common.LabelText(self, 'Time Axis'), 0, 
wx.ALIGN_CENTER)
-               x_axis_box.AddSpacer(2)
-               button_box = wx.BoxSizer(wx.HORIZONTAL)         
+               hbox = wx.BoxSizer(wx.HORIZONTAL)
+               control_box.Add(hbox, 1, wx.ALIGN_LEFT) 
+               hbox.Add(common.LabelText(self, ' Time: '), 0, 
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
                self.x_plus_button = wx.Button(self, -1, '+', 
style=wx.BU_EXACTFIT)
-               #self.x_plus_button.Bind(wx.EVT_BUTTON, self.)
-               button_box.Add(self.x_plus_button, 0, wx.ALIGN_CENTER)
+               self.x_plus_button.Bind(wx.EVT_BUTTON, self._on_incr_x_axis)
+               hbox.Add(self.x_plus_button, 0, wx.ALIGN_CENTER_VERTICAL | 
wx.ALIGN_LEFT)
                self.x_minus_button = wx.Button(self, -1, ' - ', 
style=wx.BU_EXACTFIT)
-               #self.x_minus_button.Bind(wx.EVT_BUTTON, self.)
-               button_box.Add(self.x_minus_button, 0, wx.ALIGN_CENTER)
-               x_axis_box.Add(button_box, 0, wx.ALIGN_CENTER)
-               
+               self.x_minus_button.Bind(wx.EVT_BUTTON, self._on_decr_x_axis)
+               hbox.Add(self.x_minus_button, 0, wx.ALIGN_CENTER_VERTICAL | 
wx.ALIGN_LEFT)      
                #y axis
-               y_axis_box.Add(common.LabelText(self, 'Y Axis'), 0, 
wx.ALIGN_CENTER)
-               y_axis_box.AddSpacer(2)
-               button_box = wx.BoxSizer(wx.HORIZONTAL)         
+               hbox = wx.BoxSizer(wx.HORIZONTAL)
+               control_box.Add(hbox, 1, wx.ALIGN_LEFT) 
+               hbox.Add(common.LabelText(self, ' Volts: '), 0, 
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
                self.y_plus_button = wx.Button(self, -1, '+', 
style=wx.BU_EXACTFIT)
-               #self.y_plus_button.Bind(wx.EVT_BUTTON, self.)
-               button_box.Add(self.y_plus_button, 0, wx.ALIGN_CENTER)
+               self.y_plus_button.Bind(wx.EVT_BUTTON, self._on_incr_y_axis)
+               hbox.Add(self.y_plus_button, 0, wx.ALIGN_CENTER_VERTICAL | 
wx.ALIGN_LEFT)
                self.y_minus_button = wx.Button(self, -1, ' - ', 
style=wx.BU_EXACTFIT)
-               #self.y_minus_button.Bind(wx.EVT_BUTTON, self.)
-               button_box.Add(self.y_minus_button, 0, wx.ALIGN_CENTER)
-               y_axis_box.Add(button_box, 0, wx.ALIGN_CENTER)                  
        
+               self.y_minus_button.Bind(wx.EVT_BUTTON, self._on_decr_y_axis)
+               hbox.Add(self.y_minus_button, 0, wx.ALIGN_CENTER_VERTICAL | 
wx.ALIGN_LEFT)
                
-               #autorange
-               control_box.AddSpacer(5)
-               self.autorange_check_box = wx.CheckBox(parent=self, 
style=wx.CHK_2STATE, label="Autorange")
-               #self.autorange_check_box.Bind(wx.EVT_CHECKBOX, self.)
-               control_box.Add(self.autorange_check_box, 0, wx.ALIGN_LEFT)     
        
+               #Run button
+               self.run_button = wx.Button(self, -1, '', style=wx.BU_EXACTFIT)
+               self.run_button.Bind(wx.EVT_BUTTON, self._on_run)
+               control_box.Add(self.run_button, 0, wx.ALIGN_CENTER)
+               
+               #TODO AC couple for each channel
+               #TODO autorange y axis
+               
+               #end control box
                control_box.AddStretchSpacer()
-               
                #set sizer
                self.SetSizerAndFit(control_box)
                #update
@@ -156,7 +155,10 @@
                #update the trigger button
                if self.parent.trigger_index == self.parent.input_index:
                        self.trigger_button.Disable()           
-               else: self.trigger_button.Enable()              
+               else: self.trigger_button.Enable()      
+               #update the run/stop button
+               if self.parent.running: self.run_button.SetLabel('Stop')
+               else: self.run_button.SetLabel('Run')
                #update the slider
                #TODO
                #update the trigger mode chooser
@@ -167,13 +169,15 @@
        # Event handlers
        ##################################################      
        def _on_chooser(self, event): 
-               self.parent.input_index = self.channel_chooser.GetSelection()
-               self.parent.trigger_mode_index = 
self.trigger_mode_chooser.GetSelection()
-               self.parent.trigger_level_index = 
self.trigger_level_chooser.GetSelection()
-               self.update()           
-       def _on_set_trigger(self, event):
-               self.parent.trigger_index = self.parent.input_index
-               self.update()
+               self.parent.set_input_index(self.channel_chooser.GetSelection())
+               
self.parent.set_trigger_mode_index(self.trigger_mode_chooser.GetSelection())
+               
self.parent.set_trigger_level_index(self.trigger_level_chooser.GetSelection())
+       def _on_set_trigger(self, event): 
self.parent.set_trigger_index(self.parent.input_index)
+       def _on_incr_x_axis(self, event): 
self.parent.set_x_per_div(common.get_clean_incr(self.parent.x_per_div))
+       def _on_decr_x_axis(self, event): 
self.parent.set_x_per_div(common.get_clean_decr(self.parent.x_per_div))
+       def _on_incr_y_axis(self, event): 
self.parent.set_y_per_div(common.get_clean_incr(self.parent.y_per_div))
+       def _on_decr_y_axis(self, event): 
self.parent.set_y_per_div(common.get_clean_decr(self.parent.y_per_div))
+       def _on_run(self, event): self.parent.set_run(not self.parent.running)
 
 ##################################################
 # Scope window with plotter and control panel
@@ -184,15 +188,22 @@
                parent,
                size, 
                title,
-               
+               scope,
                num_inputs,
+               x_per_div,
+               y_per_div,
        ):              
                #setup
+               self.running = True
                self.num_inputs = num_inputs
                self.input_index = 0
                self.trigger_index = 0
                self.trigger_mode_index = 0
                self.trigger_level_index = 0
+               self.x_divs = 8
+               self.x_per_div = x_per_div
+               self.y_divs = 8
+               self.y_per_div = y_per_div
                #init panel and plot 
                wx.Panel.__init__(self, parent, -1)                             
  
                self.plotter = plotter.grid_plotter(self)  
@@ -204,16 +215,114 @@
                main_box.Add(self.plotter, 1, wx.EXPAND)
                main_box.Add(self.control_panel, 0, wx.EXPAND)
                self.SetSizerAndFit(main_box)
+               #update
+               self.update()
+               
+       def update(self):
+               #update the x axis
+               self.plotter.set_x_units('Time (s)')
+               self.plotter.set_x_grid(0, self.x_per_div*self.x_divs, 
self.x_per_div)
+               #update the y axis
+               self.plotter.set_y_units('Voltage (v)')
+               self.plotter.set_y_grid(-1*self.y_per_div*self.y_divs/2, 
self.y_per_div*self.y_divs/2, self.y_per_div)
+               #update control panel
+               self.control_panel.update()
+               #update the plotter
+               self.plotter.update()
+               
+       def plot(self, sampleses):
+               if not self.running: return
+               for i, samples in enumerate(sampleses):
+                       #number of samples to scale to the screen
+                       num_samps = 
int(len(samples)/(1250*self.x_per_div*self.x_divs))
+                       #TODO handle num samps out of bounds
+                       if num_samps > len(samples) or num_samps < 2: continue
+                       self.plotter.set_waveform(
+                               channel=i, 
+                               samples=samples[:num_samps], 
+                               offset=0.0, 
+                               color_spec=CHANNEL_COLOR_SPECS[i],
+                       )               
+               #update the plotter
+               self.plotter.update()
+               
+       ##################################################
+       # Set parameters on-the-fly
+       ##################################################
+       def set_x_per_div(self, x_per_div):
+               self.x_per_div = x_per_div
+               self.update()
+       def set_y_per_div(self, y_per_div):
+               self.y_per_div = y_per_div
+               self.update()
+       def set_input_index(self, input_index):
+               self.input_index = input_index
+               self.update()
+       def set_trigger_mode_index(self, trigger_mode_index):
+               self.trigger_mode_index = trigger_mode_index
+               self.update()
+       def set_trigger_level_index(self, trigger_level_index):
+               self.trigger_level_index = trigger_level_index
+               self.update()
+       def set_trigger_index(self, trigger_index):
+               self.trigger_index = trigger_index
+               self.update()
+       def set_run(self, running):
+               self.running = running
+               self.update()
+
+##################################################
+# Scope sink block
+##################################################     
+class scope_sink_f(gr.hier_block2):
+       """!
+       A scope block with a gui window.
+       """
        
-def main(): 
-       app = wx.PySimpleApp()
-       frame = wx.Frame(None, -1, 'Demo', wx.DefaultPosition)
-       vbox = wx.BoxSizer(wx.VERTICAL)
-       win = scope_window(frame, DEFAULT_WIN_SIZE, 'Scope Demo', 4)
-       vbox.Add(win, 1, wx.EXPAND)
-       frame.SetSizerAndFit(vbox)
-       frame.Show()
-       app.MainLoop()
-       
-if __name__ == '__main__':
-       main()
+       def __init__(
+               self, 
+               parent,
+               title='', 
+               sample_rate=1,
+               size=DEFAULT_WIN_SIZE,
+               v_scale=DEFAULT_V_SCALE,
+               t_scale=None, 
+               num_inputs=1,
+       ): 
+               #TODO t_scale None is autorange
+               self.num_inputs = num_inputs
+               #init
+               gr.hier_block2.__init__(
+                       self, 
+                       "scope_sink",
+                       gr.io_signature(num_inputs, num_inputs, 
gr.sizeof_float),
+                       gr.io_signature(0, 0, 0),
+               )
+               #scope
+               msgq = gr.msg_queue(2)
+               scope = gr.oscope_sink_f(sample_rate, msgq)
+               #connect
+               for i in range(num_inputs):       
+                       self.connect((self, i), (scope, i))
+               #create window
+               self.win = scope_window(
+                       parent=parent, 
+                       size=size,
+                       title=title,
+                       scope=scope,
+                       num_inputs=num_inputs,
+                       x_per_div=t_scale,
+                       y_per_div=v_scale,
+               )
+               #register callbacks from window for external use
+               #TODO
+               #setup the input watcher
+               common.input_watcher(msgq, self._handle_msg)
+               
+       def _handle_msg(self, msg):
+               nchan = int(msg.arg1())    # number of channels of data in msg
+               nsamples = int(msg.arg2()) # number of samples in each channel
+               s = msg.to_string()      # get the body of the msg as a string
+               samples = numpy.fromstring(s, numpy.float32)
+               samps_per_ch = len(samples)/nchan               
+               self.win.plot([samples[samps_per_ch*i:samps_per_ch*(i+1)] for i 
in range(nchan)])





reply via email to

[Prev in Thread] Current Thread [Next in Thread]