commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] r6507 - in grc/trunk: examples notes src src/SignalBlo


From: jblum
Subject: [Commit-gnuradio] r6507 - in grc/trunk: examples notes src src/SignalBlockDefs src/SignalBlockDefs/ext
Date: Sun, 23 Sep 2007 11:17:05 -0600 (MDT)

Author: jblum
Date: 2007-09-23 11:17:02 -0600 (Sun, 23 Sep 2007)
New Revision: 6507

Added:
   grc/trunk/src/SignalBlockDefs/ext/
   grc/trunk/src/SignalBlockDefs/ext/__init__.py
   grc/trunk/src/SignalBlockDefs/ext/scopesink2.py
   grc/trunk/src/SignalBlockDefs/ext/selector.py
Modified:
   grc/trunk/examples/channel_distortion.grc.xml
   grc/trunk/examples/selector.grc.xml
   grc/trunk/notes/todo.txt
   grc/trunk/src/Editor.py
   grc/trunk/src/ExecFlowGraph.py
   grc/trunk/src/SignalBlockDefs/GraphicalSinks.py
   grc/trunk/src/SignalBlockDefs/Misc.py
Log:
scopesink2 with multi-inputs, moved selector to ext dir

Modified: grc/trunk/examples/channel_distortion.grc.xml
===================================================================
--- grc/trunk/examples/channel_distortion.grc.xml       2007-09-22 23:29:01 UTC 
(rev 6506)
+++ grc/trunk/examples/channel_distortion.grc.xml       2007-09-23 17:17:02 UTC 
(rev 6507)
@@ -1,8 +1,8 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <flow_graph>
-  <timestamp>1182222914.4</timestamp>
+  <timestamp>1190443645.22</timestamp>
   <hostname>tiggle</hostname>
-  <version>0.70 alpha</version>
+  <version>0.69</version>
   <valid>True</valid>
   <window_width>1200</window_width>
   <window_height>800</window_height>
@@ -21,27 +21,17 @@
       <max>5000</max>
       <step>50.0</step>
     </var>
+    <var>
+      <key>noise</key>
+      <value>.2</value>
+      <min>0</min>
+      <max>1</max>
+      <step>0.01</step>
+    </var>
   </vars>
   <signal_blocks>
     <signal_block>
       <tag>FFT Sink</tag>
-      <id>FFT Sink0</id>
-      <x_coordinate>571</x_coordinate>
-      <y_coordinate>76</y_coordinate>
-      <rotation>0</rotation>
-      <params>
-        <param>0</param>
-        <param>FFT - Distorted</param>
-        <param>$samp_rate</param>
-        <param>20</param>
-        <param>20</param>
-        <param>512</param>
-        <param>15</param>
-        <param>0</param>
-      </params>
-    </signal_block>
-    <signal_block>
-      <tag>FFT Sink</tag>
       <id>FFT Sink1</id>
       <x_coordinate>573</x_coordinate>
       <y_coordinate>266</y_coordinate>
@@ -58,16 +48,14 @@
       </params>
     </signal_block>
     <signal_block>
-      <tag>Channel Model</tag>
-      <id>Channel Model0</id>
-      <x_coordinate>317</x_coordinate>
-      <y_coordinate>101</y_coordinate>
+      <tag>About</tag>
+      <id>About0</id>
+      <x_coordinate>59</x_coordinate>
+      <y_coordinate>75</y_coordinate>
       <rotation>0</rotation>
       <params>
-        <param>.2</param>
-        <param>0.0</param>
-        <param>1.0</param>
-        <param>1.0,0.0</param>
+        <param>Channel Distortion</param>
+        <param>Josh Blum</param>
       </params>
     </signal_block>
     <signal_block>
@@ -86,16 +74,35 @@
       </params>
     </signal_block>
     <signal_block>
-      <tag>About</tag>
-      <id>About0</id>
-      <x_coordinate>59</x_coordinate>
-      <y_coordinate>75</y_coordinate>
+      <tag>FFT Sink</tag>
+      <id>FFT Sink0</id>
+      <x_coordinate>655</x_coordinate>
+      <y_coordinate>76</y_coordinate>
       <rotation>0</rotation>
       <params>
-        <param>Channel Distortion</param>
-        <param>Josh Blum</param>
+        <param>0</param>
+        <param>FFT - Distorted</param>
+        <param>$samp_rate</param>
+        <param>20</param>
+        <param>20</param>
+        <param>512</param>
+        <param>15</param>
+        <param>0</param>
       </params>
     </signal_block>
+    <signal_block>
+      <tag>Channel Model</tag>
+      <id>Channel Model0</id>
+      <x_coordinate>317</x_coordinate>
+      <y_coordinate>101</y_coordinate>
+      <rotation>0</rotation>
+      <params>
+        <param>$noise</param>
+        <param>0.0</param>
+        <param>1.0</param>
+        <param>low_pass(1, $samp_rate, 5000, 100)</param>
+      </params>
+    </signal_block>
   </signal_blocks>
   <connections>
     <connection>

Modified: grc/trunk/examples/selector.grc.xml
===================================================================
--- grc/trunk/examples/selector.grc.xml 2007-09-22 23:29:01 UTC (rev 6506)
+++ grc/trunk/examples/selector.grc.xml 2007-09-23 17:17:02 UTC (rev 6507)
@@ -1,8 +1,8 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <flow_graph>
-  <timestamp>1183066964.1</timestamp>
+  <timestamp>1190479115.22</timestamp>
   <hostname>tiggle</hostname>
-  <version>0.70 alpha</version>
+  <version>0.69</version>
   <valid>True</valid>
   <window_width>1400</window_width>
   <window_height>600</window_height>
@@ -31,19 +31,6 @@
   </vars>
   <signal_blocks>
     <signal_block>
-      <tag>PSK Modulator</tag>
-      <id>PSK Modulator0</id>
-      <x_coordinate>500</x_coordinate>
-      <y_coordinate>341</y_coordinate>
-      <rotation>0</rotation>
-      <params>
-        <param>1</param>
-        <param>2</param>
-        <param>0.35</param>
-        <param>0</param>
-      </params>
-    </signal_block>
-    <signal_block>
       <tag>GMSK Modulator</tag>
       <id>GMSK Modulator0</id>
       <x_coordinate>544</x_coordinate>
@@ -110,19 +97,6 @@
       </params>
     </signal_block>
     <signal_block>
-      <tag>Constellation Sink</tag>
-      <id>Constellation Sink0</id>
-      <x_coordinate>886</x_coordinate>
-      <y_coordinate>114</y_coordinate>
-      <rotation>180</rotation>
-      <params>
-        <param>Ouput Constellation</param>
-        <param>$samp_rate</param>
-        <param>1</param>
-        <param>0</param>
-      </params>
-    </signal_block>
-    <signal_block>
       <tag>Throttle</tag>
       <id>Throttle0</id>
       <x_coordinate>5</x_coordinate>
@@ -145,6 +119,32 @@
         <param>Josh Blum</param>
       </params>
     </signal_block>
+    <signal_block>
+      <tag>PSK Modulator</tag>
+      <id>PSK Modulator0</id>
+      <x_coordinate>503</x_coordinate>
+      <y_coordinate>340</y_coordinate>
+      <rotation>0</rotation>
+      <params>
+        <param>1</param>
+        <param>2</param>
+        <param>0.35</param>
+        <param>0</param>
+      </params>
+    </signal_block>
+    <signal_block>
+      <tag>Constellation Sink</tag>
+      <id>Constellation Sink0</id>
+      <x_coordinate>886</x_coordinate>
+      <y_coordinate>114</y_coordinate>
+      <rotation>180</rotation>
+      <params>
+        <param>Ouput Constellation</param>
+        <param>$samp_rate</param>
+        <param>1</param>
+        <param>0</param>
+      </params>
+    </signal_block>
   </signal_blocks>
   <connections>
     <connection>

Modified: grc/trunk/notes/todo.txt
===================================================================
--- grc/trunk/notes/todo.txt    2007-09-22 23:29:01 UTC (rev 6506)
+++ grc/trunk/notes/todo.txt    2007-09-23 17:17:02 UTC (rev 6507)
@@ -3,7 +3,6 @@
 -cpm (blks2)
 -filterbank (blks2)
 -usrp quad souce, set z == 1 to ignore Q inputs 
--multi-channel scope
 
 ############   Known Problems: ####################
 -packet threads block on close
@@ -12,7 +11,6 @@
 -socket controllers should be intelligent on shrinkage
 -usrp transmit dies in lock/unlock
 -audio dies lock/unlock
--channel model needs hier2
 
 ############   Features to Add:        ####################
 -startup tips

Modified: grc/trunk/src/Editor.py
===================================================================
--- grc/trunk/src/Editor.py     2007-09-22 23:29:01 UTC (rev 6506)
+++ grc/trunk/src/Editor.py     2007-09-23 17:17:02 UTC (rev 6507)
@@ -25,7 +25,7 @@
 from optparse import OptionParser
 
 if __name__ == "__main__": 
-       usage = "usage: %prog optional_flow_graphs"+FLOW_GRAPH_FILE_EXTENSION
+       usage = 'usage: %prog 
[optional_flow_graphs'+FLOW_GRAPH_FILE_EXTENSION+']'
        version = """
 GNU Radio Companion %s
 
@@ -37,11 +37,15 @@
        parser = OptionParser(usage=usage, version=version)     
        (options, args) = parser.parse_args()   
        # "test" import modules that this program will use #
+       error = False
        for module in ('pygtk', 'gtk', 'wx', 'numpy', 'xml.dom.minidom', 
'xml.dom.ext', 'gnuradio', 'gnuradio.gr.hier_block2'):
                try: __import__(module)         
-               except ImportError: #print error and exit
-                       print '\nMissing critical module: 
"%s"\nExiting!\n'%module
-                       exit(-1)
+               except ImportError: #print error
+                       error = True
+                       print '\nMissing critical module: "%s"'%module
+       if error: #exit         
+               print '\nExiting!\n'            
+               exit(-1)
        # end import of modules #
        from ActionHandler import ActionHandler
        ActionHandler(args)

Modified: grc/trunk/src/ExecFlowGraph.py
===================================================================
--- grc/trunk/src/ExecFlowGraph.py      2007-09-22 23:29:01 UTC (rev 6506)
+++ grc/trunk/src/ExecFlowGraph.py      2007-09-23 17:17:02 UTC (rev 6507)
@@ -33,8 +33,10 @@
 #      Flow Graph Builder
 
##############################################################################################
 
 class FlowGraphBuilder(gr.top_block):
-       """ Parse the input file to build the gnuradio flow graph.
-               Register the variables, handle signal block callbacks.  """
+       """
+       Parse the input file to build the gnuradio flow graph.
+       Register the variables, handle signal block callbacks.
+       """
                
        def __init__(self, file_path):          
                gr.top_block.__init__(self, file_path)  
@@ -102,16 +104,15 @@
                @param function the callback function
                @param data_type_params a list of data types
                """
-               #print "***\nBegin A callback\n%s\n\n***"%function
                try: function(*map(lambda param: param.parse(), 
data_type_params))
                except Exception, e: print "***\n\nerror parsing a callback -> 
ignoring\n%s...\n\n***"%e
-               #print "***\nEnd A callback\n***"               
                
        def parse_callbacks(self):
-               """For each call back, parse all of the data and 
-               call the registered callback function on that data."""
-               #MUTEX.lock()
-               #print "***\n\nCallback Time BEGIN\n\n***"
+               """
+               For each call back, parse all of the data and 
+               call the registered callback function on that data.
+               """
+               MUTEX.lock()
                if self.started:                        
                        if self.callbacks:      #parse regular callbacks
                                for function, data_type_params in 
self.callbacks:
@@ -121,8 +122,7 @@
                                for function, data_type_params in 
self.callbacks_locked + self.callbacks_cond:
                                        self._parse_callback(function, 
*data_type_params)
                                self.unlock()
-               #print "***\n\nCallback Time END\n\n***"
-               #MUTEX.unlock()
+               MUTEX.unlock()
                
        def _parse_nested_data(self, nested_data):
                """!
@@ -139,8 +139,8 @@
                for signal_block in signal_blocks:                      
                        signal_block,runnable_signal_block = 
SignalBlock.from_nested_data(None, signal_block, SignalBlock)                   
   
                        data_type_params = list()
-                       data_type_params.append(self)#put the flow graph in the 
front of the list
-                       for param in signal_block.get_params(): #load the list 
of arguments to the runnable block               
+                       data_type_params.append(self) #put the flow graph in 
the front of the list
+                       for param in signal_block.get_params(): #load the list 
of arguments to the runnable block               
                                data_type_params.append(param.get_data_type())  
                
                        signal_blocks_dict[signal_block.get_id()] = 
runnable_signal_block(*data_type_params)
                for connection in connections:
@@ -150,8 +150,8 @@
                        output_signal_block_id = find_data(connection, 
'output_signal_block_id')
                        output_socket_index = int(find_data(connection, 
'output_socket_index')) 
                        input_signal_block = 
signal_blocks_dict[input_signal_block_id]
-                       output_signal_block = 
signal_blocks_dict[output_signal_block_id]                        
-                       self.connect(#  use this flow graph's connect method    
#
+                       output_signal_block = 
signal_blocks_dict[output_signal_block_id]        
+                       self.connect( #use this flow graph's connect method
                                (output_signal_block, output_socket_index),
                                (input_signal_block, input_socket_index))
                                
@@ -159,18 +159,22 @@
 #      Option Parser for running a flow graph
 
##############################################################################################
                         
 class FlowGraphOptionParser(OptionParser):
-       """This flow graph option parser provides a basic help, 
-       and ensures that a flow graph is passed on the command line."""
+       """
+       This flow graph option parser provides a basic help, 
+       and ensures that a flow graph is passed on the command line.
+       """
        
        def __init__(self):
                """Create the base option parser and add usage and basic 
options."""                    
-               usage = "usage: %prog [options] 
flow_graph"+FLOW_GRAPH_FILE_EXTENSION
+               usage = 'usage: %prog [options] 
flow_graph'+FLOW_GRAPH_FILE_EXTENSION
                OptionParser.__init__(self, usage=usage)                
                self.add_option("-p", "--pid_file", action="store", 
type="string", dest="pid_file", help="record process id")   
                
        def parse_args(self):
-               """Call the base parse_args, handle the basic options,
-               and ensure a flow graph was passed in args. Return the 
(options, args)."""
+               """
+               Call the base parse_args, handle the basic options,
+               and ensure a flow graph was passed in args. Return the 
(options, args).
+               """
                (options, args) = OptionParser.parse_args(self)
                if options.pid_file:
                        try: open(options.pid_file, 'w').write('%d\n' % 
os.getpid())

Modified: grc/trunk/src/SignalBlockDefs/GraphicalSinks.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/GraphicalSinks.py     2007-09-22 23:29:01 UTC 
(rev 6506)
+++ grc/trunk/src/SignalBlockDefs/GraphicalSinks.py     2007-09-23 17:17:02 UTC 
(rev 6507)
@@ -95,7 +95,8 @@
        return sb, make
        
 def ScopeSink(sb):
-       from gnuradio.wxgui import scopesink2
+       #from gnuradio.wxgui import scopesink2
+       from ext import scopesink2      
        type = Enum([
                ('Complex', (scopesink2.scope_sink_c, Complex())),
                ('Float', (scopesink2.scope_sink_f, Float())),
@@ -107,25 +108,43 @@
        sb.add_param('Frame Decimation', Int(1))
        sb.add_param('Vertical Scale', Float(0))        
        sb.add_param('Time Scale', Float(.001))
+       sb.add_param('Marker', Enum([('Plus', 0), ('Dot', 1), ('Line', 2)], 2))
+       sb.add_param('Num Inputs', Int(1, min=1, max=4), show_label=False, 
input_sockets_controller=True)
        sb.set_docs('''\
 The scope sink has a throttle automatically attatched to it at runtime to save 
the CPU. \
 Complex inputs to the scope show up as 2 channels (real and imaginary). \
 A Vertical Scale of 0, sets the scope to auto-scale.''')       
-       def make(fg, type, title, samp_rate, frame_decim, v_scale, t_scale):
+       def make(fg, type, title, samp_rate, frame_decim, v_scale, t_scale, 
marker, num_inputs):
                v_scale = v_scale.parse()
                if v_scale == 0: v_scale = None # v_scale = None means 
auto-scale
                block = type.parse()[0](fg.get_panel(), title=title.parse(), 
                        sample_rate=samp_rate.parse(), 
frame_decim=frame_decim.parse(), 
-                       v_scale=v_scale, t_scale=t_scale.parse())
-               fg.add_window(block.win, scope_display_priority, title.parse()) 
-               throttle = gr.throttle(type.parse()[1].get_num_bytes(), 
samp_rate.parse())
-               fg.connect(throttle, block)
-               return throttle
+                       v_scale=v_scale, t_scale=t_scale.parse(), 
num_inputs=num_inputs.parse())
+               {#set the marker                
+                       0: block.win.set_format_plus,
+                       1: block.win.set_format_dot,
+                       2: block.win.set_format_line,
+               }[marker.parse()]()     
+               fg.add_window(block.win, scope_display_priority, title.parse())
+               #setup the throttles
+               scope_throttle = gr.hier_block2(
+                       'scope throttle', 
+                       gr.io_signature(num_inputs.parse(), num_inputs.parse(), 
type.parse()[1].get_num_bytes()), 
+                       gr.io_signature(num_inputs.parse(), num_inputs.parse(), 
type.parse()[1].get_num_bytes()),
+               )       
+               for i in range(num_inputs.parse()): #connect the inputs
+                       scope_throttle.connect(
+                               (scope_throttle, i), 
+                               gr.throttle(type.parse()[1].get_num_bytes(), 
samp_rate.parse()),
+                               (block, i),
+                       )
+               return scope_throttle
        return sb, make
        
 def ConstellationSink(sb):
-       from gnuradio.wxgui import scopesink2
-       fcn = scopesink2.scope_sink_c   #dont tell anyone that its really a 
scope sink
+       #from gnuradio.wxgui import scopesink2
+       from ext import scopesink2      
+       fcn = scopesink2.constellation_sink     
        sb.add_input_socket('in', Complex())
        sb.add_param('Title', String('Constellation'))
        sb.add_param('Sampling Rate', Int(default_samp_rate))   
@@ -136,11 +155,11 @@
        def make(fg, title, samp_rate, frame_decim, marker):
                block = fcn(fg.get_panel(), title=title.parse(), 
                        sample_rate=samp_rate.parse(), 
frame_decim=frame_decim.parse())
-               block.win.info.xy = True        #true for X:Y
-               marker = marker.parse()
-               if marker == 0: block.win.set_format_plus()
-               elif marker == 1: block.win.set_format_dot()
-               elif marker == 2: block.win.set_format_line()
+               {#set the marker                
+                       0: block.win.set_format_plus,
+                       1: block.win.set_format_dot,
+                       2: block.win.set_format_line,
+               }[marker.parse()]()                     
                fg.add_window(block.win, constellation_display_pritority, 
title.parse())        
                throttle = gr.throttle(Complex().get_num_bytes(), 
samp_rate.parse())
                fg.connect(throttle, block)

Modified: grc/trunk/src/SignalBlockDefs/Misc.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Misc.py       2007-09-22 23:29:01 UTC (rev 
6506)
+++ grc/trunk/src/SignalBlockDefs/Misc.py       2007-09-23 17:17:02 UTC (rev 
6507)
@@ -22,8 +22,9 @@
 
 import gnuradio.gr.gr_threading as threading
 from DataTypes import *
-from gnuradio import gr,blks
+from gnuradio import gr
 from SignalBlockConstants import default_samp_rate,all_choices,MAX_NUM_SOCKETS
+import ext as blks2
 
 def Throttle(sb):
        fcn = gr.throttle
@@ -85,98 +86,8 @@
        sb.add_param('Note', String(''))
        return sb, lambda *args: None   
 
-#######################################################################################
-##     Selector Def, and Helper Block
-#######################################################################################
-
-class SelectorHelper(gr.hier_block2):
-       """A hier2 block with N inputs and M outputs, where data is only 
forwarded through input n to output m."""
-       def __init__(self, item_size, num_inputs, num_outputs, input_index, 
output_index):      
-               """!
-               SelectorHelper constructor.
-               @param item_size the size of the gr data stream in bytes
-               @param num_inputs the number of inputs (integer)
-               @param num_outputs the number of outputs (integer)
-               @param input_index the index for the source data
-               @param output_index the index for the destination data
-               """     
-               gr.hier_block2.__init__(
-                       self, 'selector', 
-                       gr.io_signature(num_inputs, num_inputs, item_size), 
-                       gr.io_signature(num_outputs, num_outputs, item_size),
-               )
-               #terminator blocks for unused inputs and outputs        
-               self.input_terminators = [gr.null_sink(item_size) for i in 
range(num_inputs)]
-               self.output_terminators = [gr.head(item_size, 0) for i in 
range(num_outputs)]           
-               self.copy = None
-               #connections            
-               for i in range(num_inputs): self.connect((self, i), 
self.input_terminators[i])
-               for i in range(num_outputs): 
self.connect(gr.null_source(item_size), self.output_terminators[i], (self, i))  
   
-               self.item_size = item_size              
-               self.input_index = input_index
-               self.output_index = output_index        
-               self.num_inputs = num_inputs
-               self.num_outputs = num_outputs
-               self._connect_current()
-               
-       def _indexes_valid(self):
-               """!
-               Are the input and output indexes within range of the number of 
inputs and outputs?
-               @return true if input index and output index are in range
-               """
-               return self.input_index in range(self.num_inputs) and 
self.output_index in range(self.num_outputs)
-               
-       def _connect_current(self):
-               """If the input and output indexes are valid: 
-               disconnect the blocks at the input and output index from their 
terminators, 
-               and connect them to one another. Then connect the terminators 
to one another."""
-               if self._indexes_valid():
-                       self.disconnect((self, self.input_index), 
self.input_terminators[self.input_index])                             
-                       
self.disconnect(self.output_terminators[self.output_index], (self, 
self.output_index))
-                       self.copy = gr.skiphead(self.item_size, 0)
-                       self.connect((self, self.input_index), self.copy)
-                       self.connect(self.copy, (self, self.output_index))      
        
-                       
self.connect(self.output_terminators[self.output_index], 
self.input_terminators[self.input_index])      
-               
-       def _disconnect_current(self):
-               """If the input and output indexes are valid: 
-               disconnect the blocks at the input and output index from one 
another, 
-               and the terminators at the input and output index from one 
another.
-               Reconnect the blocks to the terminators."""
-               if self._indexes_valid():
-                       self.disconnect((self, self.input_index), self.copy)
-                       self.disconnect(self.copy, (self, self.output_index))
-                       
self.disconnect(self.output_terminators[self.output_index], 
self.input_terminators[self.input_index])
-                       del self.copy                   
-                       self.copy = None                        
-                       self.connect((self, self.input_index), 
self.input_terminators[self.input_index])
-                       
self.connect(self.output_terminators[self.output_index], (self, 
self.output_index))
-               
-       def set_input_index(self, input_index):
-               """!
-               Change the block to the new input index if the index changed.
-               @param input_index the new input index
-               """
-               if self.input_index != input_index:
-                       self.lock()
-                       self._disconnect_current()
-                       self.input_index = input_index
-                       self._connect_current()
-                       self.unlock()           
-               
-       def set_output_index(self, output_index):
-               """!
-               Change the block to the new output index if the index changed.
-               @param output_index the new output index
-               """             
-               if self.output_index != output_index:   
-                       self.lock()
-                       self._disconnect_current()
-                       self.output_index = output_index
-                       self._connect_current()                 
-                       self.unlock()           
-                       
 def Selector(sb):
+       fcn = blks2.selector
        type = Enum(all_choices, 1)
        vlen = Int(1, min=1)
        sb.add_input_socket('in', Variable(type), vlen=vlen)
@@ -192,7 +103,7 @@
        sb.set_docs('''Forward data from the input index to the output 
index.''')       
        def make(fg, type, input_index, output_index, num_inputs, num_outputs, 
vlen):
                item_size = type.parse().get_num_bytes()*vlen.parse()
-               block = SelectorHelper(
+               block = fcn(
                        item_size, 
                        num_inputs.parse(), 
                        num_outputs.parse(), 
@@ -205,6 +116,7 @@
        return sb, make
 
 def Valve(sb):
+       fcn = blks2.selector
        type = Enum(all_choices, 1)
        vlen = Int(1, min=1)
        sb.add_input_socket('in', Variable(type), vlen=vlen)
@@ -215,7 +127,7 @@
        sb.set_docs('''When open is 0, the valve will forward data.''') 
        def make(fg, type, open, vlen):
                item_size = type.parse().get_num_bytes()*vlen.parse()
-               block = SelectorHelper(item_size, 1, 1, 0, open.parse())
+               block = blks2.selector(item_size, 1, 1, 0, open.parse())
                fg.add_callback_locked(block.set_output_index, open)
                return block
        return sb, make

Added: grc/trunk/src/SignalBlockDefs/ext/__init__.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/ext/__init__.py                               
(rev 0)
+++ grc/trunk/src/SignalBlockDefs/ext/__init__.py       2007-09-23 17:17:02 UTC 
(rev 6507)
@@ -0,0 +1,26 @@
+"""
+Copyright 2007 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+"""
address@hidden SignalBlockDefs.ext.__init__
+#Package for external gnuradio blocks.
address@hidden Josh Blum
+
+import selector
+import scopesink2
+
+selector = selector.selector

Added: grc/trunk/src/SignalBlockDefs/ext/scopesink2.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/ext/scopesink2.py                             
(rev 0)
+++ grc/trunk/src/SignalBlockDefs/ext/scopesink2.py     2007-09-23 17:17:02 UTC 
(rev 6507)
@@ -0,0 +1,661 @@
+#!/usr/bin/env python
+#
+# Copyright 2003,2004,2006,2007 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr, gru, eng_notation
+from gnuradio.wxgui import stdgui2
+import wx
+import gnuradio.wxgui.plot as plot
+import numpy
+import threading
+import struct
+
+default_scopesink_size = (640, 240)
+default_v_scale = 1000
+default_frame_decim = gr.prefs().get_long('wxgui', 'frame_decim', 1)
+
+class scope_sink_f(gr.hier_block2):
+    def __init__(self, parent, title='', sample_rate=1,
+                 size=default_scopesink_size, frame_decim=default_frame_decim,
+                 v_scale=default_v_scale, t_scale=None, num_inputs=1):
+
+        gr.hier_block2.__init__(self, "scope_sink_f",
+                                gr.io_signature(num_inputs, num_inputs, 
gr.sizeof_float),
+                                gr.io_signature(0,0,0))
+
+        msgq = gr.msg_queue(2)         # message queue that holds at most 2 
messages
+        self.guts = gr.oscope_sink_f(sample_rate, msgq)
+        for i in range(num_inputs):        
+          self.connect((self, i), (self.guts, i))
+
+        self.win = scope_window(win_info (msgq, sample_rate, frame_decim,
+                                          v_scale, t_scale, self.guts, title), 
parent)
+
+    def set_sample_rate(self, sample_rate):
+        self.guts.set_sample_rate(sample_rate)
+        self.win.info.set_sample_rate(sample_rate)
+
+class scope_sink_c(gr.hier_block2):
+    def __init__(self, parent, title='', sample_rate=1,
+                 size=default_scopesink_size, frame_decim=default_frame_decim,
+                 v_scale=default_v_scale, t_scale=None, num_inputs=1):
+
+        gr.hier_block2.__init__(self, "scope_sink_c",
+                                gr.io_signature(num_inputs, num_inputs, 
gr.sizeof_gr_complex),
+                                gr.io_signature(0,0,0))
+
+        msgq = gr.msg_queue(2)         # message queue that holds at most 2 
messages
+        self.guts = gr.oscope_sink_f(sample_rate, msgq)
+        for i in range(num_inputs):      
+               self.c2f = gr.complex_to_float()  
+               self.connect((self, i), self.c2f)
+               self.connect((self.c2f, 0), (self.guts, 2*i+0))
+               self.connect((self.c2f, 1), (self.guts, 2*i+1))
+        
+        self.win = scope_window(win_info(msgq, sample_rate, frame_decim,
+                                         v_scale, t_scale, self.guts, title), 
parent)
+        
+    def set_sample_rate(self, sample_rate):
+        self.guts.set_sample_rate(sample_rate)
+        self.win.info.set_sample_rate(sample_rate)
+
+class constellation_sink(scope_sink_c):
+    def __init__(self, parent, title='Constellation', sample_rate=1,
+                 size=default_scopesink_size, frame_decim=default_frame_decim):
+        scope_sink_c.__init__(self, parent=parent, title=title, 
sample_rate=sample_rate,
+                 size=size, frame_decim=frame_decim)
+        self.win.info.xy = True        #constellation mode
+
+# ========================================================================
+
+
+time_base_list = [                      # time / division
+    1.0e-7,   # 100ns / div
+    2.5e-7,
+    5.0e-7,
+    1.0e-6,   #   1us / div
+    2.5e-6,
+    5.0e-6,
+    1.0e-5,   #  10us / div
+    2.5e-5,
+    5.0e-5,
+    1.0e-4,   # 100us / div
+    2.5e-4,
+    5.0e-4,
+    1.0e-3,   #   1ms / div
+    2.5e-3,
+    5.0e-3,
+    1.0e-2,   #  10ms / div
+    2.5e-2,
+    5.0e-2
+    ]
+
+v_scale_list = [ # counts / div, LARGER gains are SMALLER /div, appear EARLIER
+    2.0e-3,   # 2m / div, don't call it V/div it's actually counts/div
+    5.0e-3,
+    1.0e-2,
+    2.0e-2,
+    5.0e-2,
+    1.0e-1,
+    2.0e-1,
+    5.0e-1,
+    1.0e+0,
+    2.0e+0,
+    5.0e+0,
+    1.0e+1,
+    2.0e+1,
+    5.0e+1,
+    1.0e+2,
+    2.0e+2,
+    5.0e+2,
+    1.0e+3,
+    2.0e+3,
+    5.0e+3,
+    1.0e+4 # 10000 /div, USRP full scale is -/+ 32767
+    ]
+
+    
+wxDATA_EVENT = wx.NewEventType()
+
+def EVT_DATA_EVENT(win, func):
+    win.Connect(-1, -1, wxDATA_EVENT, func)
+
+class DataEvent(wx.PyEvent):
+    def __init__(self, data):
+        wx.PyEvent.__init__(self)
+        self.SetEventType (wxDATA_EVENT)
+        self.data = data
+
+    def Clone (self): 
+        self.__class__ (self.GetId())
+
+
+class win_info (object):
+    __slots__ = ['msgq', 'sample_rate', 'frame_decim', 'v_scale', 
+                 'scopesink', 'title',
+                 'time_scale_cursor', 'v_scale_cursor', 'marker', 'xy',
+                 'autorange', 'running']
+
+    def __init__ (self, msgq, sample_rate, frame_decim, v_scale, t_scale,
+                  scopesink, title = "Oscilloscope", xy=False):
+        self.msgq = msgq
+        self.sample_rate = sample_rate
+        self.frame_decim = frame_decim
+        self.scopesink = scopesink
+        self.title = title;
+
+        self.time_scale_cursor = gru.seq_with_cursor(time_base_list, 
initial_value = t_scale)
+        self.v_scale_cursor = gru.seq_with_cursor(v_scale_list, initial_value 
= v_scale)
+
+        self.marker = 'line'
+        self.xy = xy
+        if v_scale == None:        # 0 and None are both False, but 0 != None
+            self.autorange = True
+        else:
+            self.autorange = False # 0 is a valid v_scale            
+        self.running = True
+
+    def get_time_per_div (self):
+        return self.time_scale_cursor.current ()
+
+    def get_volts_per_div (self):
+        return self.v_scale_cursor.current ()
+
+    def set_sample_rate(self, sample_rate):
+        self.sample_rate = sample_rate
+        
+    def get_sample_rate (self):
+        return self.sample_rate
+
+    def get_decimation_rate (self):
+        return 1.0
+
+    def set_marker (self, s):
+        self.marker = s
+
+    def get_marker (self):
+        return self.marker
+
+
+class input_watcher (threading.Thread):
+    def __init__ (self, msgq, event_receiver, frame_decim, **kwds):
+        threading.Thread.__init__ (self, **kwds)
+        self.setDaemon (1)
+        self.msgq = msgq
+        self.event_receiver = event_receiver
+        self.frame_decim = frame_decim
+        self.iscan = 0
+        self.keep_running = True
+        self.start ()
+
+    def run (self):
+        # print "input_watcher: pid = ", os.getpid ()
+        while (self.keep_running):
+            msg = self.msgq.delete_head()   # blocking read of message queue
+            if self.iscan == 0:            # only display at frame_decim
+                self.iscan = self.frame_decim
+                                
+                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
+
+                bytes_per_chan = nsamples * gr.sizeof_float
+
+                records = []
+                for ch in range (nchan):
+
+                    start = ch * bytes_per_chan
+                    chan_data = s[start:start+bytes_per_chan]
+                    rec = numpy.fromstring (chan_data, numpy.float32)
+                    records.append (rec)
+
+                # print "nrecords = %d, reclen = %d" % (len (records),nsamples)
+
+                de = DataEvent (records)
+                wx.PostEvent (self.event_receiver, de)
+                records = []
+                del de
+
+            # end if iscan == 0
+            self.iscan -= 1
+    
+
+class scope_window (wx.Panel):
+
+    def __init__ (self, info, parent, id = -1,
+                  pos = wx.DefaultPosition, size = wx.DefaultSize, name = ""):
+        wx.Panel.__init__ (self, parent, -1)
+        self.info = info
+
+        vbox = wx.BoxSizer (wx.VERTICAL)
+
+        self.graph = graph_window (info, self, -1)
+
+        vbox.Add (self.graph, 1, wx.EXPAND)
+        vbox.Add (self.make_control_box(), 0, wx.EXPAND)
+        vbox.Add (self.make_control2_box(), 0, wx.EXPAND)
+
+        self.sizer = vbox
+        self.SetSizer (self.sizer)
+        self.SetAutoLayout (True)
+        self.sizer.Fit (self)
+        self.set_autorange(self.info.autorange)
+        
+
+    # second row of control buttons etc. appears BELOW control_box
+    def make_control2_box (self):
+        ctrlbox = wx.BoxSizer (wx.HORIZONTAL)
+
+        self.inc_v_button = wx.Button (self, 1101, " < ", style=wx.BU_EXACTFIT)
+        self.inc_v_button.SetToolTipString ("Increase vertical range")
+        wx.EVT_BUTTON (self, 1101, self.incr_v_scale) # ID matches button ID 
above
+
+        self.dec_v_button  = wx.Button (self, 1100, " > ", 
style=wx.BU_EXACTFIT)
+        self.dec_v_button.SetToolTipString ("Decrease vertical range")
+        wx.EVT_BUTTON (self, 1100, self.decr_v_scale)
+
+        self.v_scale_label = wx.StaticText (self, 1002, "None") # vertical /div
+        self.update_v_scale_label ()
+
+        self.autorange_checkbox = wx.CheckBox (self, 1102, "Autorange")
+        self.autorange_checkbox.SetToolTipString ("Select autorange on/off")
+        wx.EVT_CHECKBOX(self, 1102, self.autorange_checkbox_event)
+
+        ctrlbox.Add ((5,0) ,0) # left margin space
+        ctrlbox.Add (self.inc_v_button, 0, wx.EXPAND)
+        ctrlbox.Add (self.dec_v_button, 0, wx.EXPAND)
+        ctrlbox.Add (self.v_scale_label, 0, wx.ALIGN_CENTER)
+        ctrlbox.Add ((20,0) ,0) # spacer
+        ctrlbox.Add (self.autorange_checkbox, 0, wx.ALIGN_CENTER)
+
+        return ctrlbox
+
+    def make_control_box (self):
+        ctrlbox = wx.BoxSizer (wx.HORIZONTAL)
+
+        tb_left = wx.Button (self, 1001, " < ", style=wx.BU_EXACTFIT)
+        tb_left.SetToolTipString ("Increase time base")
+        wx.EVT_BUTTON (self, 1001, self.incr_timebase)
+
+
+        tb_right  = wx.Button (self, 1000, " > ", style=wx.BU_EXACTFIT)
+        tb_right.SetToolTipString ("Decrease time base")
+        wx.EVT_BUTTON (self, 1000, self.decr_timebase)
+
+        self.time_base_label = wx.StaticText (self, 1002, "")
+        self.update_timebase_label ()
+
+        ctrlbox.Add ((5,0) ,0)
+        # ctrlbox.Add (wx.StaticText (self, -1, "Horiz Scale: "), 0, 
wx.ALIGN_CENTER)
+        ctrlbox.Add (tb_left, 0, wx.EXPAND)
+        ctrlbox.Add (tb_right, 0, wx.EXPAND)
+        ctrlbox.Add (self.time_base_label, 0, wx.ALIGN_CENTER)
+
+        ctrlbox.Add ((10,0) ,1)            # stretchy space
+
+        ctrlbox.Add (wx.StaticText (self, -1, "Trig: "), 0, wx.ALIGN_CENTER)
+        self.trig_chan_choice = wx.Choice (self, 1004,
+                                           choices = ['Ch1', 'Ch2', 'Ch3', 
'Ch4'])
+        self.trig_chan_choice.SetToolTipString ("Select channel for trigger")
+        wx.EVT_CHOICE (self, 1004, self.trig_chan_choice_event)
+        ctrlbox.Add (self.trig_chan_choice, 0, wx.ALIGN_CENTER)
+
+        self.trig_mode_choice = wx.Choice (self, 1005,
+                                           choices = ['Auto', 'Pos', 'Neg'])
+        self.trig_mode_choice.SetToolTipString ("Select trigger slope or Auto 
(untriggered roll)")
+        wx.EVT_CHOICE (self, 1005, self.trig_mode_choice_event)
+        ctrlbox.Add (self.trig_mode_choice, 0, wx.ALIGN_CENTER)
+
+        trig_level50 = wx.Button (self, 1006, "50%")
+        trig_level50.SetToolTipString ("Set trigger level to 50%")
+        wx.EVT_BUTTON (self, 1006, self.set_trig_level50)
+        ctrlbox.Add (trig_level50, 0, wx.EXPAND)
+
+        run_stop = wx.Button (self, 1007, "Run/Stop")
+        run_stop.SetToolTipString ("Toggle Run/Stop mode")
+        wx.EVT_BUTTON (self, 1007, self.run_stop)
+        ctrlbox.Add (run_stop, 0, wx.EXPAND)
+
+        ctrlbox.Add ((10, 0) ,1)            # stretchy space
+
+        ctrlbox.Add (wx.StaticText (self, -1, "Fmt: "), 0, wx.ALIGN_CENTER)
+        self.marker_choice = wx.Choice (self, 1002, choices = 
self._marker_choices)
+        self.marker_choice.SetToolTipString ("Select plotting with lines, 
pluses or dots")
+        wx.EVT_CHOICE (self, 1002, self.marker_choice_event)
+        ctrlbox.Add (self.marker_choice, 0, wx.ALIGN_CENTER)
+
+        self.xy_choice = wx.Choice (self, 1003, choices = ['X:t', 'X:Y'])
+        self.xy_choice.SetToolTipString ("Select X vs time or X vs Y display")
+        wx.EVT_CHOICE (self, 1003, self.xy_choice_event)
+        ctrlbox.Add (self.xy_choice, 0, wx.ALIGN_CENTER)
+
+        return ctrlbox
+    
+    _marker_choices = ['line', 'plus', 'dot']
+
+    def update_timebase_label (self):
+        time_per_div = self.info.get_time_per_div ()
+        s = ' ' + eng_notation.num_to_str (time_per_div) + 's/div'
+        self.time_base_label.SetLabel (s)
+        
+    def decr_timebase (self, evt):
+        self.info.time_scale_cursor.prev ()
+        self.update_timebase_label ()
+
+    def incr_timebase (self, evt):
+        self.info.time_scale_cursor.next ()
+        self.update_timebase_label ()
+
+    def update_v_scale_label (self):
+        volts_per_div = self.info.get_volts_per_div ()
+        s = ' ' + eng_notation.num_to_str (volts_per_div) + '/div' # Not V/div
+        self.v_scale_label.SetLabel (s)
+        
+    def decr_v_scale (self, evt):
+        self.info.v_scale_cursor.prev ()
+        self.update_v_scale_label ()
+
+    def incr_v_scale (self, evt):
+        self.info.v_scale_cursor.next ()
+        self.update_v_scale_label ()
+        
+    def marker_choice_event (self, evt):
+        s = evt.GetString ()
+        self.set_marker (s)
+
+    def set_autorange(self, on):
+        if on:
+            self.v_scale_label.SetLabel(" (auto)")
+            self.info.autorange = True
+            self.autorange_checkbox.SetValue(True)
+            self.inc_v_button.Enable(False)
+            self.dec_v_button.Enable(False)
+        else:
+            if self.graph.y_range:
+                (l,u) = self.graph.y_range # found by autorange
+                self.info.v_scale_cursor.set_index_by_value((u-l)/8.0)
+            self.update_v_scale_label()
+            self.info.autorange = False
+            self.autorange_checkbox.SetValue(False)
+            self.inc_v_button.Enable(True)
+            self.dec_v_button.Enable(True)
+            
+    def autorange_checkbox_event(self, evt):
+        if evt.Checked():
+            self.set_autorange(True)
+        else:
+            self.set_autorange(False)
+            
+    def set_marker (self, s):
+        self.info.set_marker (s)        # set info for drawing routines
+        i = self.marker_choice.FindString (s)
+        assert i >= 0, "Hmmm, set_marker problem"
+        self.marker_choice.SetSelection (i)
+
+    def set_format_line (self):
+        self.set_marker ('line')
+
+    def set_format_dot (self):
+        self.set_marker ('dot')
+
+    def set_format_plus (self):
+        self.set_marker ('plus')
+        
+    def xy_choice_event (self, evt):
+        s = evt.GetString ()
+        self.info.xy = s == 'X:Y'
+
+    def trig_chan_choice_event (self, evt):
+        s = evt.GetString ()
+        ch = int (s[-1]) - 1
+        self.info.scopesink.set_trigger_channel (ch)
+
+    def trig_mode_choice_event (self, evt):
+        sink = self.info.scopesink
+        s = evt.GetString ()
+        if s == 'Pos':
+            sink.set_trigger_mode (gr.gr_TRIG_POS_SLOPE)
+        elif s == 'Neg':
+            sink.set_trigger_mode (gr.gr_TRIG_NEG_SLOPE)
+        elif s == 'Auto':
+            sink.set_trigger_mode (gr.gr_TRIG_AUTO)
+        else:
+            assert 0, "Bad trig_mode_choice string"
+    
+    def set_trig_level50 (self, evt):
+        self.info.scopesink.set_trigger_level_auto ()
+
+    def run_stop (self, evt):
+        self.info.running = not self.info.running
+        
+
+class graph_window (plot.PlotCanvas):
+
+    channel_colors = ['BLUE', 'RED',
+                      'CYAN', 'MAGENTA', 'GREEN', 'YELLOW']
+    
+    def __init__ (self, info, parent, id = -1,
+                  pos = wx.DefaultPosition, size = (640, 240),
+                  style = wx.DEFAULT_FRAME_STYLE, name = ""):
+        plot.PlotCanvas.__init__ (self, parent, id, pos, size, style, name)
+
+        self.SetXUseScopeTicks (True)
+        self.SetEnableGrid (True)
+        self.SetEnableZoom (True)
+        self.SetEnableLegend(True)
+        # self.SetBackgroundColour ('black')
+        
+        self.info = info;
+        self.y_range = None
+        self.x_range = None
+        self.avg_y_min = None
+        self.avg_y_max = None
+        self.avg_x_min = None
+        self.avg_x_max = None
+
+        EVT_DATA_EVENT (self, self.format_data)
+
+        self.input_watcher = input_watcher (info.msgq, self, info.frame_decim)
+
+    def channel_color (self, ch):
+        return self.channel_colors[ch % len(self.channel_colors)]
+       
+    def format_data (self, evt):
+        if not self.info.running:
+            return
+        
+        if self.info.xy:
+            self.format_xy_data (evt)
+            return
+
+        info = self.info
+        records = evt.data
+        nchannels = len (records)
+        npoints = len (records[0])
+
+        objects = []
+
+        Ts = 1.0 / (info.get_sample_rate () / info.get_decimation_rate ())
+        x_vals = Ts * numpy.arange (-npoints/2, npoints/2)
+
+        # preliminary clipping based on time axis here, instead of in graphics 
code
+        time_per_window = self.info.get_time_per_div () * 10
+        n = int (time_per_window / Ts + 0.5)
+        n = n & ~0x1                    # make even
+        n = max (2, min (n, npoints))
+
+        self.SetXUseScopeTicks (True)   # use 10 divisions, no labels
+
+        for ch in range(nchannels):
+            r = records[ch]
+
+            # plot middle n points of record
+
+            lb = npoints/2 - n/2
+            ub = npoints/2 + n/2
+            # points = zip (x_vals[lb:ub], r[lb:ub])
+            points = numpy.zeros ((ub-lb, 2), numpy.float64)
+            points[:,0] = x_vals[lb:ub]
+            points[:,1] = r[lb:ub]
+
+            m = info.get_marker ()
+            if m == 'line':
+                objects.append (plot.PolyLine (points,
+                                               colour=self.channel_color (ch),
+                                               legend=('Ch%d' % (ch+1,))))
+            else:
+                objects.append (plot.PolyMarker (points,
+                                                 marker=m,
+                                                 colour=self.channel_color 
(ch),
+                                                 legend=('Ch%d' % (ch+1,))))
+
+        graphics = plot.PlotGraphics (objects,
+                                      title=self.info.title,
+                                      xLabel = '', yLabel = '')
+
+        time_per_div = info.get_time_per_div ()
+        x_range = (-5.0 * time_per_div, 5.0 * time_per_div) # ranges are 
tuples!
+        volts_per_div = info.get_volts_per_div ()
+        if not self.info.autorange:
+            self.y_range = (-4.0 * volts_per_div, 4.0 * volts_per_div)
+        self.Draw (graphics, xAxis=x_range, yAxis=self.y_range)
+        self.update_y_range () # autorange to self.y_range
+
+
+    def format_xy_data (self, evt):
+        info = self.info
+        records = evt.data
+        nchannels = len (records)
+        npoints = len (records[0])
+
+        if nchannels < 2:
+            return
+
+        objects = []
+        # points = zip (records[0], records[1])
+        points = numpy.zeros ((len(records[0]), 2), numpy.float32)
+        points[:,0] = records[0]
+        points[:,1] = records[1]
+        
+        self.SetXUseScopeTicks (False)
+
+        m = info.get_marker ()
+        if m == 'line':
+            objects.append (plot.PolyLine (points,
+                                           colour=self.channel_color (0)))
+        else:
+            objects.append (plot.PolyMarker (points,
+                                             marker=m,
+                                             colour=self.channel_color (0)))
+
+        graphics = plot.PlotGraphics (objects,
+                                      title=self.info.title,
+                                      xLabel = 'I', yLabel = 'Q')
+
+        self.Draw (graphics, xAxis=self.x_range, yAxis=self.y_range)
+        self.update_y_range ()
+        self.update_x_range ()
+
+
+    def update_y_range (self):
+        alpha = 1.0/25
+        graphics = self.last_draw[0]
+        p1, p2 = graphics.boundingBox ()     # min, max points of graphics
+
+        if self.avg_y_min: # prevent vertical scale from jumping abruptly --?
+            self.avg_y_min = p1[1] * alpha + self.avg_y_min * (1 - alpha)
+            self.avg_y_max = p2[1] * alpha + self.avg_y_max * (1 - alpha)
+        else: # initial guess
+            self.avg_y_min = p1[1] # -500.0 workaround, sometimes p1 is ~ 10^35
+            self.avg_y_max = p2[1] # 500.0
+
+        self.y_range = self._axisInterval ('auto', self.avg_y_min, 
self.avg_y_max)
+        # print "p1 %s  p2 %s  y_min %s  y_max %s  y_range %s" \
+        #        % (p1, p2, self.avg_y_min, self.avg_y_max, self.y_range)
+
+
+    def update_x_range (self):
+        alpha = 1.0/25
+        graphics = self.last_draw[0]
+        p1, p2 = graphics.boundingBox ()     # min, max points of graphics
+
+        if self.avg_x_min:
+            self.avg_x_min = p1[0] * alpha + self.avg_x_min * (1 - alpha)
+            self.avg_x_max = p2[0] * alpha + self.avg_x_max * (1 - alpha)
+        else:
+            self.avg_x_min = p1[0]
+            self.avg_x_max = p2[0]
+
+        self.x_range = self._axisInterval ('auto', self.avg_x_min, 
self.avg_x_max)
+
+
+# ----------------------------------------------------------------
+# Stand-alone test application
+# ----------------------------------------------------------------
+
+class test_top_block (stdgui2.std_top_block):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv)
+
+        if len(argv) > 1:
+            frame_decim = int(argv[1]) 
+        else:
+            frame_decim = 1
+
+        if len(argv) > 2:
+            v_scale = float(argv[2])  # start up at this v_scale value
+        else:
+            v_scale = None  # start up in autorange mode, default
+
+        if len(argv) > 3:
+            t_scale = float(argv[3])  # start up at this t_scale value
+        else:
+            t_scale = None  # old behavior
+
+        print "frame decim %s  v_scale %s  t_scale %s" % 
(frame_decim,v_scale,t_scale)
+            
+        input_rate = 1e6
+
+        # Generate a complex sinusoid
+        self.src0 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 25.1e3, 1e3)
+
+        # We add this throttle block so that this demo doesn't suck down
+        # all the CPU available.  You normally wouldn't use it...
+        self.thr = gr.throttle(gr.sizeof_gr_complex, input_rate)
+
+        scope = scope_sink_c (panel,"Secret Data",sample_rate=input_rate,
+                              frame_decim=frame_decim,
+                              v_scale=v_scale, t_scale=t_scale)
+        vbox.Add (scope.win, 1, wx.EXPAND)
+
+        # Ultimately this will be
+        # self.connect("src0 throttle scope")
+       self.connect(self.src0, self.thr, scope) 
+
+def main ():
+    app = stdgui2.stdapp (test_top_block, "O'Scope Test App")
+    app.MainLoop ()
+
+if __name__ == '__main__':
+    main ()
+
+# ----------------------------------------------------------------

Added: grc/trunk/src/SignalBlockDefs/ext/selector.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/ext/selector.py                               
(rev 0)
+++ grc/trunk/src/SignalBlockDefs/ext/selector.py       2007-09-23 17:17:02 UTC 
(rev 6507)
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+#
+# Copyright 2003,2004,2006,2007 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr
+
+class selector(gr.hier_block2):
+       """A hier2 block with N inputs and M outputs, where data is only 
forwarded through input n to output m."""
+       def __init__(self, item_size, num_inputs, num_outputs, input_index, 
output_index):      
+               """!
+               SelectorHelper constructor.
+               @param item_size the size of the gr data stream in bytes
+               @param num_inputs the number of inputs (integer)
+               @param num_outputs the number of outputs (integer)
+               @param input_index the index for the source data
+               @param output_index the index for the destination data
+               """     
+               gr.hier_block2.__init__(
+                       self, 'selector', 
+                       gr.io_signature(num_inputs, num_inputs, item_size), 
+                       gr.io_signature(num_outputs, num_outputs, item_size),
+               )
+               #terminator blocks for unused inputs and outputs        
+               self.input_terminators = [gr.null_sink(item_size) for i in 
range(num_inputs)]
+               self.output_terminators = [gr.head(item_size, 0) for i in 
range(num_outputs)]           
+               self.copy = None
+               #connections            
+               for i in range(num_inputs): self.connect((self, i), 
self.input_terminators[i])
+               for i in range(num_outputs): 
self.connect(gr.null_source(item_size), self.output_terminators[i], (self, i))  
   
+               self.item_size = item_size              
+               self.input_index = input_index
+               self.output_index = output_index        
+               self.num_inputs = num_inputs
+               self.num_outputs = num_outputs
+               self._connect_current()
+               
+       def _indexes_valid(self):
+               """!
+               Are the input and output indexes within range of the number of 
inputs and outputs?
+               @return true if input index and output index are in range
+               """
+               return self.input_index in range(self.num_inputs) and 
self.output_index in range(self.num_outputs)
+               
+       def _connect_current(self):
+               """If the input and output indexes are valid: 
+               disconnect the blocks at the input and output index from their 
terminators, 
+               and connect them to one another. Then connect the terminators 
to one another."""
+               if self._indexes_valid():
+                       self.disconnect((self, self.input_index), 
self.input_terminators[self.input_index])                             
+                       
self.disconnect(self.output_terminators[self.output_index], (self, 
self.output_index))
+                       self.copy = gr.skiphead(self.item_size, 0)
+                       self.connect((self, self.input_index), self.copy)
+                       self.connect(self.copy, (self, self.output_index))      
        
+                       
self.connect(self.output_terminators[self.output_index], 
self.input_terminators[self.input_index])      
+               
+       def _disconnect_current(self):
+               """If the input and output indexes are valid: 
+               disconnect the blocks at the input and output index from one 
another, 
+               and the terminators at the input and output index from one 
another.
+               Reconnect the blocks to the terminators."""
+               if self._indexes_valid():
+                       self.disconnect((self, self.input_index), self.copy)
+                       self.disconnect(self.copy, (self, self.output_index))
+                       
self.disconnect(self.output_terminators[self.output_index], 
self.input_terminators[self.input_index])
+                       del self.copy                   
+                       self.copy = None                        
+                       self.connect((self, self.input_index), 
self.input_terminators[self.input_index])
+                       
self.connect(self.output_terminators[self.output_index], (self, 
self.output_index))
+               
+       def set_input_index(self, input_index):
+               """!
+               Change the block to the new input index if the index changed.
+               @param input_index the new input index
+               """
+               if self.input_index != input_index:
+                       self.lock()
+                       self._disconnect_current()
+                       self.input_index = input_index
+                       self._connect_current()
+                       self.unlock()           
+               
+       def set_output_index(self, output_index):
+               """!
+               Change the block to the new output index if the index changed.
+               @param output_index the new output index
+               """             
+               if self.output_index != output_index:   
+                       self.lock()
+                       self._disconnect_current()
+                       self.output_index = output_index
+                       self._connect_current()                 
+                       self.unlock()   
+





reply via email to

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