[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r8751 - gnuradio/branches/developers/jblum/gr-wxglgui/
From: |
jblum |
Subject: |
[Commit-gnuradio] r8751 - gnuradio/branches/developers/jblum/gr-wxglgui/src/python |
Date: |
Sun, 29 Jun 2008 23:15:55 -0600 (MDT) |
Author: jblum
Date: 2008-06-29 23:15:55 -0600 (Sun, 29 Jun 2008)
New Revision: 8751
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:
added more callbacks, fft block chain moved to common, scopesink frame rate
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
2008-06-29 20:22:03 UTC (rev 8750)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
2008-06-30 05:15:55 UTC (rev 8751)
@@ -19,11 +19,97 @@
# Boston, MA 02110-1301, USA.
#
+from gnuradio import gr, window
import threading
import numpy
import math
import wx
+##################################################
+# FFT blocks chain: input -> message sink
+##################################################
+class _fft_chain_base(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, sample_rate, fft_size, frame_rate, ref_scale,
avg_alpha, average):
+ """!
+ Create an fft block.
+ Write the samples to a message sink.
+ Provide access to the msg queue, setting the filter, and sample
rate.
+ @param sample_rate, fft_size, frame_rate, ref_scale, avg_alpha,
average the fft parameters
+ """
+ self.fft_size = fft_size
+ self.frame_rate = frame_rate
+ #init
+ gr.hier_block2.__init__(
+ self,
+ "fft_block",
+ gr.io_signature(1, 1, self.item_size),
+ gr.io_signature(0, 0, 0),
+ )
+ #create blocks
+ s2p = gr.stream_to_vector(self.item_size, fft_size)
+ self.one_in_n = gr.keep_one_in_n(self.item_size * fft_size, 1)
+ #create fft
+ fft_window = window.blackmanharris(fft_size)
+ fft = self.fft_block[0](fft_size, True, fft_window)
+ power = sum(map(lambda x: x*x, fft_window))
+ #filter fft, convert to dB
+ c2mag = gr.complex_to_mag(fft_size)
+ self.avg = gr.single_pole_iir_filter_ff(1.0, fft_size)
+ log = gr.nlog10_ff(
+ 20,
+ fft_size,
+ -10*math.log10(fft_size) # Adjust for number of bins
+ -10*math.log10(power/fft_size) # Adjust for windowing
loss
+ -20*math.log10(ref_scale/2) # Adjust for reference scale
+ )
+ #message sink
+ self.msgq = gr.msg_queue(2)
+ sink = gr.message_sink(gr.sizeof_float*fft_size, self.msgq,
True)
+ #connect
+ self.connect(self, s2p, self.one_in_n, fft, c2mag, self.avg,
log, sink)
+ #initial update
+ self.set_sample_rate(sample_rate)
+ self.set_average(average)
+ self.set_avg_alpha(avg_alpha)
+
+ def set_sample_rate(self, sample_rate):
+ """!
+ Set the new sampling rate and update the decimator.
+ @param sample_rate the new rate
+ """
+ self.sample_rate = sample_rate
+ self.one_in_n.set_n(max(1,
int(self.sample_rate/self.fft_size/self.frame_rate)))
+
+ def set_average(self, average):
+ """!
+ Set the averaging filter on/off.
+ @param average true to set averaging on
+ """
+ self.average = average
+ if self.average: self.avg.set_taps(self.avg_alpha)
+ else: self.avg.set_taps(1.0)
+
+ def set_avg_alpha(self, avg_alpha):
+ """!
+ Set the average alpha and set the taps if average was on.
+ @param avg_alpha the new iir filter tap
+ """
+ self.avg_alpha = avg_alpha
+ self.set_average(self.average)
+
+class fft_chain_f(_fft_chain_base):
+ item_size = gr.sizeof_float
+ fft_block = (gr.fft_vfc, )
+class fft_chain_c(_fft_chain_base):
+ item_size = gr.sizeof_gr_complex
+ fft_block = (gr.fft_vcc, )
+
class LabelText(wx.StaticText):
"""!
Label text to give the wx plots a uniform look.
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
2008-06-29 20:22:03 UTC (rev 8750)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
2008-06-30 05:15:55 UTC (rev 8751)
@@ -22,7 +22,7 @@
##################################################
# Imports
##################################################
-from gnuradio import gr, window
+from gnuradio import gr
import plotter
import common
import wx
@@ -138,6 +138,7 @@
average,
peak_hold,
set_average,
+ set_sample_rate,
):
#ensure y_per_div
if y_per_div not in DIV_LEVELS: y_per_div = DIV_LEVELS[0]
@@ -152,6 +153,7 @@
self.average = average
self.peak_hold = peak_hold
self.fft_set_average = set_average
+ self.fft_set_sample_rate = set_sample_rate
self.peak_vals = []
#init panel and plot
wx.Panel.__init__(self, parent, -1)
@@ -196,8 +198,9 @@
self.plotter.update()
def update(self):
- #update average
+ #update fft block
self.fft_set_average(self.average)
+ self.fft_set_sample_rate(self.sample_rate)
#update peak hold
if not self.peak_hold: self.peak_vals = []
#determine best fitting x_per_div
@@ -235,6 +238,9 @@
##################################################
# Set parameters on-the-fly
##################################################
+ def set_sample_rate(self, sample_rate):
+ self.sample_rate = sample_rate
+ self.update()
def set_baseband_freq(self, baseband_freq):
self.baseband_freq = baseband_freq
self.update()
@@ -254,66 +260,6 @@
def decr_ref_level(self): self.set_ref_level(self.ref_level -
self.y_per_div)
##################################################
-# FFT blocks chain: input -> message sink
-##################################################
-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, 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, frame_rate, ref_scale, avg_alpha
the fft parameters
- """
- self._avg_alpha = avg_alpha
- #init
- gr.hier_block2.__init__(
- self,
- "fft_block",
- gr.io_signature(1, 1, item_size),
- gr.io_signature(0, 0, 0),
- )
- #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/frame_rate)))
- #create fft
- fft_window = window.blackmanharris(fft_size)
- fft = {
- gr.sizeof_float: gr.fft_vfc,
- gr.sizeof_gr_complex: gr.fft_vcc
- }[item_size](fft_size, True, fft_window)
- power = sum(map(lambda x: x*x, fft_window))
- #filter fft, convert to dB
- c2mag = gr.complex_to_mag(fft_size)
- self._avg = gr.single_pole_iir_filter_ff(1.0, fft_size)
- log = gr.nlog10_ff(
- 20,
- fft_size,
- -10*math.log10(fft_size) # Adjust for number of bins
- -10*math.log10(power/fft_size) # Adjust for windowing
loss
- -20*math.log10(ref_scale/2) # Adjust for reference scale
- )
- #message sink
- self.msgq = gr.msg_queue(2)
- sink = gr.message_sink(gr.sizeof_float*fft_size, self.msgq,
True)
- #connect
- self.connect(self, s2p, one_in_n, fft, c2mag, self._avg, log,
sink)
-
- def set_average(self, average):
- """!
- Set the averaging filter on/off.
- @param average true to set averaging on
- """
- if average: self._avg.set_taps(self._avg_alpha)
- else: self._avg.set_taps(1.0)
-
-##################################################
# FFT sink base block for real and complex types
##################################################
class _fft_sink_base(gr.hier_block2):
@@ -338,7 +284,6 @@
size=DEFAULT_WIN_SIZE,
peak_hold=False,
):
- self.real = self.item_size == gr.sizeof_float
#ensure avg alpha
if avg_alpha is None: avg_alpha = 2.0/frame_rate
#init
@@ -350,13 +295,13 @@
)
copy = gr.kludge_copy(self.item_size)
#fft block
- fft = fft_block(
- item_size=self.item_size,
+ fft = self.fft_chain(
sample_rate=sample_rate,
fft_size=fft_size,
frame_rate=frame_rate,
ref_scale=ref_scale,
avg_alpha=avg_alpha,
+ average=average,
)
#connect
self.connect(self, copy, fft)
@@ -373,7 +318,8 @@
ref_level=ref_level,
average=average,
peak_hold=peak_hold,
- set_average=fft.set_average,
+ set_average=fft.set_average,
+ set_sample_rate=fft.set_sample_rate,
)
#register callbacks from window for external use
self.set_baseband_freq = self.win.set_baseband_freq
@@ -381,6 +327,8 @@
self.set_peak_hold = self.win.set_peak_hold
self.set_y_per_div = self.win.set_y_per_div
self.set_ref_level = self.win.set_ref_level
+ self.set_avg_alpha = fft.set_avg_alpha
+ self.set_sample_rate = self.win.set_sample_rate
#setup the input watcher
common.input_watcher(fft.msgq, self._handle_msg)
@@ -408,5 +356,11 @@
#plot
self.win.plot(samples)
-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
+class fft_sink_f(_fft_sink_base):
+ fft_chain = common.fft_chain_f
+ item_size = gr.sizeof_float
+ real = True
+class fft_sink_c(_fft_sink_base):
+ fft_chain = common.fft_chain_c
+ item_size = gr.sizeof_gr_complex
+ real = False
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
2008-06-29 20:22:03 UTC (rev 8750)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
2008-06-30 05:15:55 UTC (rev 8751)
@@ -33,6 +33,7 @@
##################################################
# Constants
##################################################
+DEFAULT_FRAME_RATE = 30
DEFAULT_WIN_SIZE = (640, 240)
DEFAULT_V_SCALE = 1000
TRIGGER_MODES = (
@@ -206,6 +207,7 @@
size,
title,
scope,
+ frame_rate,
num_inputs,
sample_rate,
x_per_div,
@@ -224,7 +226,7 @@
self.autorange_ts = 0
self.input_index = 0
self.trigger_index = 0
- self.trigger_mode_index = 0
+ self.trigger_mode_index = 1
self.trigger_level_index = 0
self.x_divs = 8
self.x_per_div = x_per_div
@@ -232,9 +234,11 @@
if y_per_div is None: self.y_per_div = 1
else: self.y_per_div = y_per_div
self.scope = scope
+ self.frame_rate = frame_rate
+ self.frame_counter = 0
self._init = False #HACK
#init panel and plot
- wx.Panel.__init__(self, parent, -1)
+ wx.Panel.__init__(self, parent, -1)
self.plotter = plotter.grid_plotter(self)
self.plotter.SetSize(wx.Size(*size))
self.plotter.set_title(title)
@@ -258,32 +262,36 @@
self._init = True
self.update()
if not self.running: return
- for i, samples in enumerate(sampleses):
- #number of samples to scale to the screen
- num_samps =
int(self.x_per_div*self.x_divs*self.sample_rate)
- #ac coupling
- if self.ac_couple[i]: samples = samples -
numpy.average(samples)
- #autorange
- if self.autorange_index == i and \
- time.time() - self.autorange_ts >
AUTORANGE_UPDATE_RATE:
- rms = numpy.average(numpy.square(samples))**.5
- mean = numpy.average(samples)
- y_per_div =
common.get_clean_num(4*(rms+mean)/self.y_divs)
- if self.y_per_div != y_per_div:
self.set_y_per_div(y_per_div)
- self.autorange_ts = time.time()
- #handle num samps out of bounds
- if num_samps > len(samples) or num_samps < 2: continue
- #plot samples
- self.plotter.set_waveform(
- channel=i+1,
- samples=samples[:num_samps],
- offset=0.0,
- color_spec=CHANNEL_COLOR_SPECS[i],
- )
- #update the plotter
- self.plotter.update()
+ if self.frame_counter == 0: #decimate
+ for i, samples in enumerate(sampleses):
+ #number of samples to scale to the screen
+ num_samps =
int(self.x_per_div*self.x_divs*self.sample_rate)
+ #ac coupling
+ if self.ac_couple[i]: samples = samples -
numpy.average(samples)
+ #autorange
+ if self.autorange_index == i and \
+ time.time() - self.autorange_ts >
AUTORANGE_UPDATE_RATE:
+ rms =
numpy.average(numpy.square(samples))**.5
+ mean = numpy.average(samples)
+ y_per_div =
common.get_clean_num(4*(rms+mean)/self.y_divs)
+ if self.y_per_div != y_per_div:
self.set_y_per_div(y_per_div)
+ self.autorange_ts = time.time()
+ #handle num samps out of bounds
+ if num_samps > len(samples) or num_samps < 2:
continue
+ #plot samples
+ self.plotter.set_waveform(
+ channel=i+1,
+ samples=samples[:num_samps],
+ offset=0.0,
+ color_spec=CHANNEL_COLOR_SPECS[i],
+ )
+ #update the plotter
+ self.plotter.update()
+ self.frame_counter = (self.frame_counter + 1)%self.decim
def update(self):
+ #update the frame decimation
+ self.decim = max(1,
int(self.sample_rate/self.scope.get_samples_per_output_record()/self.frame_rate))
#update the scope
if self._init: #HACK avoid segfaults, only set after a sample
has arrived
self.scope.set_trigger_channel(self.trigger_index)
@@ -358,6 +366,7 @@
title='',
sample_rate=1,
size=DEFAULT_WIN_SIZE,
+ frame_rate=DEFAULT_FRAME_RATE,
v_scale=DEFAULT_V_SCALE,
t_scale=None,
num_inputs=1,
@@ -383,6 +392,7 @@
size=size,
title=title,
scope=scope,
+ frame_rate=frame_rate,
num_inputs=num_inputs,
sample_rate=sample_rate,
x_per_div=t_scale,
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r8751 - gnuradio/branches/developers/jblum/gr-wxglgui/src/python,
jblum <=