[Top][All Lists]
[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()
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r6507 - in grc/trunk: examples notes src src/SignalBlockDefs src/SignalBlockDefs/ext,
jblum <=