commit-gnuradio
[Top][All Lists]
Advanced

[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,





reply via email to

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