[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r8745 - gnuradio/branches/developers/jblum/gr-wxglgui/
From: |
jblum |
Subject: |
[Commit-gnuradio] r8745 - gnuradio/branches/developers/jblum/gr-wxglgui/src/python |
Date: |
Sat, 28 Jun 2008 21:13:52 -0600 (MDT) |
Author: jblum
Date: 2008-06-28 21:13:51 -0600 (Sat, 28 Jun 2008)
New Revision: 8745
Modified:
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
Log:
work on scopesink
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
2008-06-29 03:07:54 UTC (rev 8744)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
2008-06-29 03:13:51 UTC (rev 8745)
@@ -20,6 +20,8 @@
#
import threading
+import numpy
+import math
import wx
class LabelText(wx.StaticText):
@@ -52,3 +54,51 @@
def run(self):
while self.keep_running:
self.handle_msg(self.msgq.delete_head())
+
+def get_exp(num):
+ """!
+ Get the exponent of the number in base 10.
+ @param num the floating point number
+ @return the exponent as an integer
+ """
+ return int(math.floor(math.log10(num)))
+
+def get_clean_num(num):
+ """!
+ Get the closest clean number match to num with bases 1, 2, 5.
+ @param num the number
+ @return the closest number
+ """
+ exp = get_exp(num)
+ nums = numpy.array((1, 2, 5, 10))*(10**exp)
+ return nums[numpy.argmin(numpy.abs(nums - num))]
+
+def get_clean_incr(num):
+ """!
+ Get the next higher clean number with bases 1, 2, 5.
+ @param num the number
+ @return the next higher number
+ """
+ exp = get_exp(num)
+ num = get_clean_num(num)
+ base = int(num/10**exp)
+ return {
+ 1: 2,
+ 2: 5,
+ 5: 10,
+ }[base]*(10**exp)
+
+def get_clean_decr(num):
+ """!
+ Get the next lower clean number with bases 1, 2, 5.
+ @param num the number
+ @return the next lower number
+ """
+ exp = get_exp(num)
+ num = get_clean_num(num)
+ base = int(num/10**exp)
+ return {
+ 1: .5,
+ 2: 1,
+ 5: 2,
+ }[base]*(10**exp)
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
2008-06-29 03:07:54 UTC (rev 8744)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
2008-06-29 03:13:51 UTC (rev 8745)
@@ -32,7 +32,7 @@
##################################################
# Constants
##################################################
-DEFAULT_FFT_RATE = gr.prefs().get_long('wxgui', 'fft_rate', 15)
+DEFAULT_FRAME_RATE = 30
DEFAULT_WIN_SIZE = (640, 240)
DIV_LEVELS = (1, 2, 5, 10, 20)
FFT_PLOT_COLOR_SPEC = (0, 0, 1)
@@ -202,9 +202,8 @@
#determine best fitting x_per_div
if self.real: x_width = self.sample_rate/2.0
else: x_width = self.sample_rate
- exp = math.floor(math.log10(x_width/self.x_divs))
- x_per_divs = numpy.array((1, 2, 5, 10))*10**exp
- x_per_div = x_per_divs[numpy.argmin(numpy.abs(x_per_divs -
x_width/self.x_divs))]
+ x_per_div = common.get_clean_num(x_width/self.x_divs)
+ exp = common.get_exp(x_per_div)
#calculate units and scalar
if exp >= 9: x_units, scalar = 'GHz', 1e-9
elif exp >= 6: x_units, scalar = 'MHz', 1e-6
@@ -227,7 +226,7 @@
self.plotter.set_x_units('Frequency (%s)'%x_units)
#update y grid
self.plotter.set_y_grid(self.ref_level-self.y_per_div*self.y_divs,
self.ref_level, self.y_per_div)
- #update control panel if non-gui changes occured
+ #update control panel
self.control_panel.update()
#update the plotter
self.plotter.update()
@@ -259,15 +258,17 @@
class fft_block(gr.hier_block2):
"""!
Create an fft block chain, with real/complex input.
+ The fft stream is written to a message sink.
+ This block provides a callback to set the average on/off.
"""
- def __init__(self, item_size, sample_rate, fft_size, fft_rate,
ref_scale, avg_alpha):
+ def __init__(self, item_size, sample_rate, fft_size, frame_rate,
ref_scale, avg_alpha):
"""!
Create an fft block.
Write the samples to a message sink.
Provide access to the msg queue and setting the filter.
@param item_size the input size complex or float
- @param sample_rate, fft_size, fft_rate, ref_scale, avg_alpha
the fft parameters
+ @param sample_rate, fft_size, frame_rate, ref_scale, avg_alpha
the fft parameters
"""
self._avg_alpha = avg_alpha
#init
@@ -279,7 +280,7 @@
)
#create blocks
s2p = gr.stream_to_vector(item_size, fft_size)
- one_in_n = gr.keep_one_in_n(item_size * fft_size, max(1,
int(sample_rate/fft_size/fft_rate)))
+ one_in_n = gr.keep_one_in_n(item_size * fft_size, max(1,
int(sample_rate/fft_size/frame_rate)))
#create fft
fft_window = window.blackmanharris(fft_size)
fft = {
@@ -316,9 +317,7 @@
##################################################
class _fft_sink_base(gr.hier_block2):
"""!
- An fft block with real/complex inputs.
- The fft stream is written to a message sink.
- This block provides a callback to set the average on/off.
+ An fft block with real/complex inputs and a gui window.
"""
def __init__(
@@ -331,7 +330,7 @@
ref_level=50,
sample_rate=1,
fft_size=512,
- fft_rate=DEFAULT_FFT_RATE,
+ frame_rate=DEFAULT_FRAME_RATE,
average=False,
avg_alpha=None,
title='',
@@ -340,7 +339,7 @@
):
self.real = self.item_size == gr.sizeof_float
#ensure avg alpha
- if avg_alpha is None: avg_alpha = 2.0/fft_rate
+ if avg_alpha is None: avg_alpha = 2.0/frame_rate
#init
gr.hier_block2.__init__(
self,
@@ -354,7 +353,7 @@
item_size=self.item_size,
sample_rate=sample_rate,
fft_size=fft_size,
- fft_rate=fft_rate,
+ frame_rate=frame_rate,
ref_scale=ref_scale,
avg_alpha=avg_alpha,
)
@@ -410,64 +409,3 @@
class fft_sink_f(_fft_sink_base): item_size = gr.sizeof_float
class fft_sink_c(_fft_sink_base): item_size = gr.sizeof_gr_complex
-
-# ----------------------------------------------------------------
-# Standalone test app
-# ----------------------------------------------------------------
-
-class test_app_block (gr.top_block):
- def __init__(self, frame, vbox):
- gr.top_block.__init__(self)
- fft_size = 256
-
- # build our flow graph
- input_rate = 20.48e3
-
- # Generate a complex sinusoid
- #src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 2e3, 1)
- src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1)
-
- # We add these throttle blocks so that this demo doesn't
- # suck down all the CPU available. Normally you wouldn't use
these.
- thr1 = gr.throttle(gr.sizeof_gr_complex, input_rate)
-
- sink1 = fft_sink_c (frame, title="Complex Data",
fft_size=fft_size,
- sample_rate=input_rate,
baseband_freq=100e3,
- ref_level=0,
y_per_div=20, y_divs=10)
- vbox.Add (sink1.win, 1, wx.EXPAND)
-
- self.connect(src1, thr1, sink1)
-
- #src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 1)
- src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1)
- thr2 = gr.throttle(gr.sizeof_float, input_rate)
- sink2 = fft_sink_f (frame, title="Real Data",
fft_size=fft_size*2,
- sample_rate=input_rate,
baseband_freq=100e3,
- ref_level=0,
y_per_div=20, y_divs=10)
- vbox.Add (sink2.win, 1, wx.EXPAND)
-
- self.connect(src2, thr2, sink2)
- self.start()
-
-def main ():
- app = wx.PySimpleApp()
- frame = wx.Frame(None, -1, 'Demo', wx.DefaultPosition)
- vbox = wx.BoxSizer(wx.VERTICAL)
- test_app_block(frame, vbox)
- frame.SetSizerAndFit(vbox)
- frame.SetSize(wx.Size(800, 500))
- frame.Show()
- app.MainLoop()
-
-if __name__ == '__main__':
- main ()
- #tb = gr.top_block()
- #src1 = gr.sig_source_f (23e3, gr.GR_CONST_WAVE, 5.75e3, 1)
- #def handle_samples(samp):
- # print len(samp)
- #fft = fft_block(4, 23e3, 256, 1., 1., 1.)
- #tb.connect(src1, fft)
- #tb.start()
- #input_watcher(fft.msgq, handle_samples)
- #raw_input()
-
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
2008-06-29 03:07:54 UTC (rev 8744)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
2008-06-29 03:13:51 UTC (rev 8745)
@@ -32,20 +32,25 @@
##################################################
# Constants
##################################################
-DEFAULT_FRAME_DECIM = gr.prefs().get_long('wxgui', 'frame_decim', 15)
DEFAULT_WIN_SIZE = (640, 240)
DEFAULT_V_SCALE = 1000
TRIGGER_MODES = (
- ('Automatic', gr.gr_TRIG_AUTO),
- ('Negative', gr.gr_TRIG_NEG_SLOPE),
- ('Positive', gr.gr_TRIG_POS_SLOPE),
+ ('Auto', gr.gr_TRIG_AUTO),
+ ('Neg', gr.gr_TRIG_NEG_SLOPE),
+ ('Pos', gr.gr_TRIG_POS_SLOPE),
)
TRIGGER_LEVELS = (
- ('Automatic', None),
+ ('Auto', None),
('Low', -0.5),
- ('Medium', 0.0),
+ ('Med', 0.0),
('High', 0.5),
)
+CHANNEL_COLOR_SPECS = (
+ (0, 0, 1),
+ (0, 1, 0),
+ (1, 0, 0),
+ (1, 1, 0),
+)
##################################################
# Scope window control panel
@@ -66,7 +71,6 @@
#begin control box
control_box.AddStretchSpacer()
control_box.Add(common.LabelText(self, 'Select Channel'), 0,
wx.ALIGN_CENTER)
- control_box.AddSpacer(2)
#channel and trigger box
channel_trigger_box = wx.BoxSizer(wx.HORIZONTAL)
control_box.Add(channel_trigger_box, 0, wx.EXPAND)
@@ -82,66 +86,61 @@
#offset slider
control_box.AddStretchSpacer()
control_box.Add(common.LabelText(self, 'Channel Offset'), 0,
wx.ALIGN_CENTER)
- control_box.AddSpacer(2)
self.offset_slider = wx.Slider(self, -1, style=wx.SL_HORIZONTAL)
control_box.Add(self.offset_slider, 0, wx.EXPAND)
- #trigger mode
+ #trigger menu
control_box.AddStretchSpacer()
- control_box.Add(common.LabelText(self, 'Trigger Mode'), 0,
wx.ALIGN_CENTER)
- control_box.AddSpacer(2)
+ control_box.Add(common.LabelText(self, 'Trigger Menu'), 0,
wx.ALIGN_CENTER)
+ #trigger mode
+ hbox = wx.BoxSizer(wx.HORIZONTAL)
+ control_box.Add(hbox, 1, wx.ALIGN_LEFT)
+ hbox.Add(common.LabelText(self, ' Mode: '), 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
self.trigger_mode_chooser = wx.Choice(self, -1, choices=[tm[0]
for tm in TRIGGER_MODES])
self.trigger_mode_chooser.Bind(wx.EVT_CHOICE, self._on_chooser)
- control_box.Add(self.trigger_mode_chooser, 0, wx.ALIGN_CENTER)
-
+ hbox.Add(self.trigger_mode_chooser, 0, wx.ALIGN_CENTER_VERTICAL
| wx.ALIGN_LEFT)
#trigger level
- control_box.AddStretchSpacer()
- control_box.Add(common.LabelText(self, 'Trigger Level'), 0,
wx.ALIGN_CENTER)
- control_box.AddSpacer(2)
+ hbox = wx.BoxSizer(wx.HORIZONTAL)
+ control_box.Add(hbox, 1, wx.ALIGN_LEFT)
+ hbox.Add(common.LabelText(self, ' Level: '), 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
self.trigger_level_chooser = wx.Choice(self, -1, choices=[tl[0]
for tl in TRIGGER_LEVELS])
self.trigger_level_chooser.Bind(wx.EVT_CHOICE, self._on_chooser)
- control_box.Add(self.trigger_level_chooser, 0, wx.ALIGN_CENTER)
+ hbox.Add(self.trigger_level_chooser, 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
- #setup axis boxes
- axis_box = wx.BoxSizer(wx.HORIZONTAL)
- x_axis_box = wx.BoxSizer(wx.VERTICAL)
- y_axis_box = wx.BoxSizer(wx.VERTICAL)
- axis_box.Add(x_axis_box, 1, wx.EXPAND)
- axis_box.Add(y_axis_box, 1, wx.EXPAND)
+ #setup axes menu
control_box.AddStretchSpacer()
- control_box.Add(axis_box, 0, wx.ALIGN_CENTER)
-
+ control_box.Add(common.LabelText(self, 'Axes Menu'), 0,
wx.ALIGN_CENTER)
#x axis
- x_axis_box.Add(common.LabelText(self, 'Time Axis'), 0,
wx.ALIGN_CENTER)
- x_axis_box.AddSpacer(2)
- button_box = wx.BoxSizer(wx.HORIZONTAL)
+ hbox = wx.BoxSizer(wx.HORIZONTAL)
+ control_box.Add(hbox, 1, wx.ALIGN_LEFT)
+ hbox.Add(common.LabelText(self, ' Time: '), 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
self.x_plus_button = wx.Button(self, -1, '+',
style=wx.BU_EXACTFIT)
- #self.x_plus_button.Bind(wx.EVT_BUTTON, self.)
- button_box.Add(self.x_plus_button, 0, wx.ALIGN_CENTER)
+ self.x_plus_button.Bind(wx.EVT_BUTTON, self._on_incr_x_axis)
+ hbox.Add(self.x_plus_button, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_LEFT)
self.x_minus_button = wx.Button(self, -1, ' - ',
style=wx.BU_EXACTFIT)
- #self.x_minus_button.Bind(wx.EVT_BUTTON, self.)
- button_box.Add(self.x_minus_button, 0, wx.ALIGN_CENTER)
- x_axis_box.Add(button_box, 0, wx.ALIGN_CENTER)
-
+ self.x_minus_button.Bind(wx.EVT_BUTTON, self._on_decr_x_axis)
+ hbox.Add(self.x_minus_button, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_LEFT)
#y axis
- y_axis_box.Add(common.LabelText(self, 'Y Axis'), 0,
wx.ALIGN_CENTER)
- y_axis_box.AddSpacer(2)
- button_box = wx.BoxSizer(wx.HORIZONTAL)
+ hbox = wx.BoxSizer(wx.HORIZONTAL)
+ control_box.Add(hbox, 1, wx.ALIGN_LEFT)
+ hbox.Add(common.LabelText(self, ' Volts: '), 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
self.y_plus_button = wx.Button(self, -1, '+',
style=wx.BU_EXACTFIT)
- #self.y_plus_button.Bind(wx.EVT_BUTTON, self.)
- button_box.Add(self.y_plus_button, 0, wx.ALIGN_CENTER)
+ self.y_plus_button.Bind(wx.EVT_BUTTON, self._on_incr_y_axis)
+ hbox.Add(self.y_plus_button, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_LEFT)
self.y_minus_button = wx.Button(self, -1, ' - ',
style=wx.BU_EXACTFIT)
- #self.y_minus_button.Bind(wx.EVT_BUTTON, self.)
- button_box.Add(self.y_minus_button, 0, wx.ALIGN_CENTER)
- y_axis_box.Add(button_box, 0, wx.ALIGN_CENTER)
+ self.y_minus_button.Bind(wx.EVT_BUTTON, self._on_decr_y_axis)
+ hbox.Add(self.y_minus_button, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_LEFT)
- #autorange
- control_box.AddSpacer(5)
- self.autorange_check_box = wx.CheckBox(parent=self,
style=wx.CHK_2STATE, label="Autorange")
- #self.autorange_check_box.Bind(wx.EVT_CHECKBOX, self.)
- control_box.Add(self.autorange_check_box, 0, wx.ALIGN_LEFT)
+ #Run button
+ self.run_button = wx.Button(self, -1, '', style=wx.BU_EXACTFIT)
+ self.run_button.Bind(wx.EVT_BUTTON, self._on_run)
+ control_box.Add(self.run_button, 0, wx.ALIGN_CENTER)
+
+ #TODO AC couple for each channel
+ #TODO autorange y axis
+
+ #end control box
control_box.AddStretchSpacer()
-
#set sizer
self.SetSizerAndFit(control_box)
#update
@@ -156,7 +155,10 @@
#update the trigger button
if self.parent.trigger_index == self.parent.input_index:
self.trigger_button.Disable()
- else: self.trigger_button.Enable()
+ else: self.trigger_button.Enable()
+ #update the run/stop button
+ if self.parent.running: self.run_button.SetLabel('Stop')
+ else: self.run_button.SetLabel('Run')
#update the slider
#TODO
#update the trigger mode chooser
@@ -167,13 +169,15 @@
# Event handlers
##################################################
def _on_chooser(self, event):
- self.parent.input_index = self.channel_chooser.GetSelection()
- self.parent.trigger_mode_index =
self.trigger_mode_chooser.GetSelection()
- self.parent.trigger_level_index =
self.trigger_level_chooser.GetSelection()
- self.update()
- def _on_set_trigger(self, event):
- self.parent.trigger_index = self.parent.input_index
- self.update()
+ self.parent.set_input_index(self.channel_chooser.GetSelection())
+
self.parent.set_trigger_mode_index(self.trigger_mode_chooser.GetSelection())
+
self.parent.set_trigger_level_index(self.trigger_level_chooser.GetSelection())
+ def _on_set_trigger(self, event):
self.parent.set_trigger_index(self.parent.input_index)
+ def _on_incr_x_axis(self, event):
self.parent.set_x_per_div(common.get_clean_incr(self.parent.x_per_div))
+ def _on_decr_x_axis(self, event):
self.parent.set_x_per_div(common.get_clean_decr(self.parent.x_per_div))
+ def _on_incr_y_axis(self, event):
self.parent.set_y_per_div(common.get_clean_incr(self.parent.y_per_div))
+ def _on_decr_y_axis(self, event):
self.parent.set_y_per_div(common.get_clean_decr(self.parent.y_per_div))
+ def _on_run(self, event): self.parent.set_run(not self.parent.running)
##################################################
# Scope window with plotter and control panel
@@ -184,15 +188,22 @@
parent,
size,
title,
-
+ scope,
num_inputs,
+ x_per_div,
+ y_per_div,
):
#setup
+ self.running = True
self.num_inputs = num_inputs
self.input_index = 0
self.trigger_index = 0
self.trigger_mode_index = 0
self.trigger_level_index = 0
+ self.x_divs = 8
+ self.x_per_div = x_per_div
+ self.y_divs = 8
+ self.y_per_div = y_per_div
#init panel and plot
wx.Panel.__init__(self, parent, -1)
self.plotter = plotter.grid_plotter(self)
@@ -204,16 +215,114 @@
main_box.Add(self.plotter, 1, wx.EXPAND)
main_box.Add(self.control_panel, 0, wx.EXPAND)
self.SetSizerAndFit(main_box)
+ #update
+ self.update()
+
+ def update(self):
+ #update the x axis
+ self.plotter.set_x_units('Time (s)')
+ self.plotter.set_x_grid(0, self.x_per_div*self.x_divs,
self.x_per_div)
+ #update the y axis
+ self.plotter.set_y_units('Voltage (v)')
+ self.plotter.set_y_grid(-1*self.y_per_div*self.y_divs/2,
self.y_per_div*self.y_divs/2, self.y_per_div)
+ #update control panel
+ self.control_panel.update()
+ #update the plotter
+ self.plotter.update()
+
+ def plot(self, sampleses):
+ if not self.running: return
+ for i, samples in enumerate(sampleses):
+ #number of samples to scale to the screen
+ num_samps =
int(len(samples)/(1250*self.x_per_div*self.x_divs))
+ #TODO handle num samps out of bounds
+ if num_samps > len(samples) or num_samps < 2: continue
+ self.plotter.set_waveform(
+ channel=i,
+ samples=samples[:num_samps],
+ offset=0.0,
+ color_spec=CHANNEL_COLOR_SPECS[i],
+ )
+ #update the plotter
+ self.plotter.update()
+
+ ##################################################
+ # Set parameters on-the-fly
+ ##################################################
+ def set_x_per_div(self, x_per_div):
+ self.x_per_div = x_per_div
+ self.update()
+ def set_y_per_div(self, y_per_div):
+ self.y_per_div = y_per_div
+ self.update()
+ def set_input_index(self, input_index):
+ self.input_index = input_index
+ self.update()
+ def set_trigger_mode_index(self, trigger_mode_index):
+ self.trigger_mode_index = trigger_mode_index
+ self.update()
+ def set_trigger_level_index(self, trigger_level_index):
+ self.trigger_level_index = trigger_level_index
+ self.update()
+ def set_trigger_index(self, trigger_index):
+ self.trigger_index = trigger_index
+ self.update()
+ def set_run(self, running):
+ self.running = running
+ self.update()
+
+##################################################
+# Scope sink block
+##################################################
+class scope_sink_f(gr.hier_block2):
+ """!
+ A scope block with a gui window.
+ """
-def main():
- app = wx.PySimpleApp()
- frame = wx.Frame(None, -1, 'Demo', wx.DefaultPosition)
- vbox = wx.BoxSizer(wx.VERTICAL)
- win = scope_window(frame, DEFAULT_WIN_SIZE, 'Scope Demo', 4)
- vbox.Add(win, 1, wx.EXPAND)
- frame.SetSizerAndFit(vbox)
- frame.Show()
- app.MainLoop()
-
-if __name__ == '__main__':
- main()
+ def __init__(
+ self,
+ parent,
+ title='',
+ sample_rate=1,
+ size=DEFAULT_WIN_SIZE,
+ v_scale=DEFAULT_V_SCALE,
+ t_scale=None,
+ num_inputs=1,
+ ):
+ #TODO t_scale None is autorange
+ self.num_inputs = num_inputs
+ #init
+ gr.hier_block2.__init__(
+ self,
+ "scope_sink",
+ gr.io_signature(num_inputs, num_inputs,
gr.sizeof_float),
+ gr.io_signature(0, 0, 0),
+ )
+ #scope
+ msgq = gr.msg_queue(2)
+ scope = gr.oscope_sink_f(sample_rate, msgq)
+ #connect
+ for i in range(num_inputs):
+ self.connect((self, i), (scope, i))
+ #create window
+ self.win = scope_window(
+ parent=parent,
+ size=size,
+ title=title,
+ scope=scope,
+ num_inputs=num_inputs,
+ x_per_div=t_scale,
+ y_per_div=v_scale,
+ )
+ #register callbacks from window for external use
+ #TODO
+ #setup the input watcher
+ common.input_watcher(msgq, self._handle_msg)
+
+ def _handle_msg(self, msg):
+ nchan = int(msg.arg1()) # number of channels of data in msg
+ nsamples = int(msg.arg2()) # number of samples in each channel
+ s = msg.to_string() # get the body of the msg as a string
+ samples = numpy.fromstring(s, numpy.float32)
+ samps_per_ch = len(samples)/nchan
+ self.win.plot([samples[samps_per_ch*i:samps_per_ch*(i+1)] for i
in range(nchan)])
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r8745 - gnuradio/branches/developers/jblum/gr-wxglgui/src/python,
jblum <=