commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] r8758 - gnuradio/branches/developers/jblum/gr-wxglgui/


From: jblum
Subject: [Commit-gnuradio] r8758 - gnuradio/branches/developers/jblum/gr-wxglgui/src/python
Date: Mon, 30 Jun 2008 18:28:47 -0600 (MDT)

Author: jblum
Date: 2008-06-30 18:28:46 -0600 (Mon, 30 Jun 2008)
New Revision: 8758

Added:
   gnuradio/branches/developers/jblum/gr-wxglgui/src/python/constsink.py
Modified:
   gnuradio/branches/developers/jblum/gr-wxglgui/src/python/Makefile.am
   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/plotter.py
   gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
Log:
work on constsink, split fft block chain into fft + stream decimator for reuse

Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/Makefile.am
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/Makefile.am        
2008-07-01 00:26:53 UTC (rev 8757)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/Makefile.am        
2008-07-01 00:28:46 UTC (rev 8758)
@@ -33,5 +33,6 @@
        gltext.py \
        plotter.py \
        common.py \
+       constsink.py \
        fftsink.py \
        scopesink.py

Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py  
2008-07-01 00:26:53 UTC (rev 8757)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py  
2008-07-01 00:28:46 UTC (rev 8758)
@@ -26,8 +26,49 @@
 import wx
 
 ##################################################
-# FFT blocks chain: input -> message sink
+# Stream decimator chain
 ##################################################     
+class stream_decimator(gr.hier_block2):
+       """!
+       Convert the stream to a vector, decimate the vector to achieve the 
vector rate.
+       """
+       
+       def __init__(self, item_size, sample_rate, vec_rate, vec_len):
+               """!
+               Create the block chain.
+               @param item_size the number of bytes per sample
+               @param sample_rate the rate of incoming samples
+               @param vec_rate the rate of outgoing vectors
+               @param vec_len the length of the outgoing vectors
+               """
+               self.vec_rate = vec_rate
+               self.vec_len = vec_len
+               #init
+               gr.hier_block2.__init__(
+                       self, 
+                       "stream_decimator_block",
+                       gr.io_signature(1, 1, item_size),
+                       gr.io_signature(1, 1, item_size*vec_len),
+               )
+               #create blocks
+               s2v = gr.stream_to_vector(item_size, vec_len)           
+               self.one_in_n = gr.keep_one_in_n(item_size * vec_len, 1)
+               #connect
+               self.connect(self, s2v, self.one_in_n, self)
+               #initial update
+               self.set_sample_rate(sample_rate)
+               
+       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.vec_len/self.vec_rate)))
+
+##################################################
+# FFT block chain
+##################################################     
 class _fft_chain_base(gr.hier_block2):
        """!
        Create an fft block chain, with real/complex input.
@@ -38,22 +79,23 @@
        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.
+               Provide access to the 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),
+                       gr.io_signature(1, 1, gr.sizeof_float*fft_size),
                )
                #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)  
        
+               self.sd = stream_decimator(
+                       item_size=self.item_size,
+                       sample_rate=sample_rate,
+                       vec_rate=frame_rate,
+                       vec_len=fft_size,
+               )
                #create fft
                fft_window = window.blackmanharris(fft_size)
                fft = self.fft_block[0](fft_size, True, fft_window)
@@ -68,13 +110,11 @@
                        -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)
+               self.connect(self, self.sd, fft, c2mag, self.avg, log, self)
+               #register
+               self.set_sample_rate = self.sd.set_sample_rate
                #initial update
-               self.set_sample_rate(sample_rate)
                self.set_average(average)
                self.set_avg_alpha(avg_alpha)           
 

Added: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/constsink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/constsink.py       
                        (rev 0)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/constsink.py       
2008-07-01 00:28:46 UTC (rev 8758)
@@ -0,0 +1,202 @@
+#
+# Copyright 2008 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.
+# 
+
+##################################################
+# Imports
+##################################################
+from gnuradio import gr
+import plotter
+import common
+import wx
+import numpy
+import time
+
+##################################################
+# Constants
+##################################################
+DEFAULT_FRAME_RATE = 30
+DEFAULT_WIN_SIZE = (400, 400)
+DEFAULT_CONST_SIZE = 1024
+CONST_PLOT_COLOR_SPEC = (0, 0, 1) 
+
+##################################################
+# Constellation window control panel
+##################################################
+class control_panel(wx.Panel):
+       """!
+       A control panel with wx widgits to control the plotter.
+       """
+       def __init__(self, parent):     
+               """!
+               Create a new control panel.
+               @param parent the wx parent window
+               """
+               self.parent = parent
+               wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)     
+               control_box = wx.BoxSizer(wx.HORIZONTAL)
+               
+               #begin control box
+               control_box.AddSpacer(2)
+               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.EXPAND)          
+               #end control box
+               control_box.AddSpacer(2)
+               #set sizer
+               self.SetSizerAndFit(control_box)
+               #update
+               self.update()
+               
+       def update(self): 
+               #update the run/stop button
+               if self.parent.running: self.run_button.SetLabel('Stop')
+               else: self.run_button.SetLabel('Run')
+               
+       ##################################################
+       # Event handlers
+       ##################################################
+       def _on_run(self, event): self.parent.set_run(not self.parent.running)
+               
+##################################################
+# Constellation window with plotter and control panel
+##################################################
+class const_window(wx.Panel):
+       def __init__(
+               self, 
+               parent,
+               size, 
+               title,
+               frame_rate,
+               sample_rate,
+       ):              
+               #setup
+               self.running = True
+               self.sample_rate = sample_rate
+               self.x_divs = 8
+               self.x_per_div = 1
+               self.x_off = 0
+               self.y_divs = 8
+               self.y_per_div = 1
+               self.y_off = 0
+               #init panel and plot 
+               wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER)
+               self.plotter = plotter.grid_plotter(self)  
+               self.plotter.SetSize(wx.Size(*size))
+               self.plotter.set_title(title)
+               self.plotter.set_x_units('Inphase')
+               self.plotter.set_y_units('Quadrature')
+               #setup the box with plot and controls
+               self.control_panel = control_panel(self)
+               main_box = wx.BoxSizer(wx.VERTICAL)
+               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 plot(self, samples):
+               """!
+               Plot the samples onto the complex grid.
+               @param samples the array of complex samples
+               """     
+               if not self.running: return
+               real = numpy.real(samples)
+               imag = numpy.imag(samples)
+               samples = zip((real, imag))
+               self.plotter.set_waveform(
+                       channel=0, 
+                       samples=samples,
+                       color_spec=CONST_PLOT_COLOR_SPEC,
+               )
+
+       def update(self): 
+               #update the grid
+               #update control panel and plotter
+               self.control_panel.update()
+               self.plotter.update()
+               
+       ##################################################
+       # Set parameters on-the-fly
+       ##################################################
+       def set_run(self, running):
+               self.running = running
+               self.update()
+
+##################################################
+# Constellation sink block
+##################################################     
+class const_sink_c(gr.hier_block2):
+       """!
+       A constellation block with a gui window.
+       """
+       
+       def __init__(
+               self, 
+               parent,
+               title='', 
+               sample_rate=1,
+               size=DEFAULT_WIN_SIZE,
+               frame_rate=DEFAULT_FRAME_RATE,
+               const_size=DEFAULT_CONST_SIZE,
+       ):
+               #init
+               gr.hier_block2.__init__(
+                       self, 
+                       "const_sink",
+                       gr.io_signature(1, 1, gr.sizeof_gr_complex),
+                       gr.io_signature(0, 0, 0),
+               )
+               #blocks
+               sd = common.stream_decimator(
+                       item_size=gr.sizeof_gr_complex,
+                       sample_rate=sample_rate,
+                       vec_rate=frame_rate,
+                       vec_len=const_size,
+               )
+               msgq = gr.msg_queue(2)
+               sink = gr.message_sink(gr.sizeof_gr_complex*const_size, msgq, 
True)
+               #connect
+               self.connect(self, sd, sink)
+               #create window
+               self.win = const_window(
+                       parent=parent, 
+                       size=size,
+                       title=title,
+                       frame_rate=frame_rate,
+                       sample_rate=sample_rate,
+               )
+               #register callbacks from window for external use
+               self.set_sample_rate = sd.set_sample_rate
+               #setup the input watcher
+               common.input_watcher(msgq, self._handle_msg)
+               
+       def _handle_msg(self, msg):
+               itemsize = int(msg.arg1())
+               nitems = int(msg.arg2())
+               s = msg.to_string()
+               # There may be more than one frame in the message.
+               # If so, we take only the last one
+               if nitems > 1:
+                       start = itemsize * (nitems - 1)
+                       s = s[start:start+itemsize]             
+               #convert to complex floating point numbers
+               samples = numpy.fromstring(s, numpy.complex64)
+               self.win.plot(samples)

Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py 
2008-07-01 00:26:53 UTC (rev 8757)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py 
2008-07-01 00:28:46 UTC (rev 8758)
@@ -26,7 +26,6 @@
 import plotter
 import common
 import wx
-import math
 import numpy
 
 ##################################################
@@ -52,7 +51,7 @@
                @param parent the wx parent window
                """
                self.parent = parent
-               wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER)     
+               wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)     
                control_box = wx.BoxSizer(wx.VERTICAL)
                
                #checkboxes for average and peak hold
@@ -156,7 +155,7 @@
                self.fft_set_sample_rate = set_sample_rate
                self.peak_vals = []
                #init panel and plot 
-               wx.Panel.__init__(self, parent, -1)                             
  
+               wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER)     
                          
                self.plotter = plotter.grid_plotter(self)  
                self.plotter.SetSize(wx.Size(*size))
                self.plotter.set_title(title)
@@ -228,9 +227,8 @@
                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
+               #update control panel and plotter
                self.control_panel.update()
-               #update the plotter
                self.plotter.update()
        
        ##################################################
@@ -291,8 +289,8 @@
                        gr.io_signature(1, 1, self.item_size),
                        gr.io_signature(0, 0, 0),
                )
+               #blocks
                copy = gr.kludge_copy(self.item_size)
-               #fft block
                fft = self.fft_chain(
                        sample_rate=sample_rate, 
                        fft_size=fft_size, 
@@ -301,8 +299,10 @@
                        avg_alpha=avg_alpha,
                        average=average,
                )
+               msgq = gr.msg_queue(2)
+               sink = gr.message_sink(gr.sizeof_float*fft_size, msgq, True)
                #connect
-               self.connect(self, copy, fft)
+               self.connect(self, copy, fft, sink)
                #create window
                self.win = fft_window(
                        parent=parent, 
@@ -328,7 +328,7 @@
                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)
+               common.input_watcher(msgq, self._handle_msg)
                
        def _handle_msg(self, msg):
                """!

Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py 
2008-07-01 00:26:53 UTC (rev 8757)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py 
2008-07-01 00:28:46 UTC (rev 8758)
@@ -26,6 +26,7 @@
 from OpenGL.GLU import *
 from OpenGL.GL import *
 
+import threading
 import gltext
 import common
 import math
@@ -38,7 +39,7 @@
 UNITS_TEXT_FONT_SIZE = 9
 LEGEND_TEXT_FONT_SIZE = 8
 LEGEND_BOX_WIDTH, LEGEND_BOX_HEIGHT = 26, 20
-PADDING = 35, 10, 40, 60 #top, right, bottom, left
+PADDING = 35, 15, 40, 60 #top, right, bottom, left
 
 class _plotter_base(wx.glcanvas.GLCanvas):
        """!
@@ -68,7 +69,7 @@
                """!
                Respond to paint events, call update.
                Initialize GL if this is the first paint event.
-               """
+               """             
                self.SetCurrent()
                #check if gl was initialized
                if not self._gl_init_flag:
@@ -97,7 +98,8 @@
        def __init__(self, parent):
                """!
                Create a new grid plotter.
-               """             
+               """
+               self.semaphore = threading.Semaphore(1)
                self.grid_compiled_list_id = wx.NewId()
                self.channels = dict()  
                #store title and unit strings
@@ -117,32 +119,40 @@
                Set the legend on/off.
                @param legend true to turn on
                """
+               self.semaphore.acquire(True)
                self.legend = legend
-               self._changed = True    
+               self._changed = True
+               self.semaphore.release()        
        
        def set_title(self, title):
                """!
                Set the title.
                @param title the title string
                """
+               self.semaphore.acquire(True)
                self.title = title
                self._changed = True
+               self.semaphore.release()
 
        def set_x_units(self, x_units):
                """!
                Set the x_units.
                @param x_units the x_units string
                """
+               self.semaphore.acquire(True)
                self.x_units = x_units
                self._changed = True
+               self.semaphore.release()
 
        def set_y_units(self, y_units):
                """!
                Set the y_units.
                @param y_units the y_units string
                """
+               self.semaphore.acquire(True)
                self.y_units = y_units
                self._changed = True
+               self.semaphore.release()
 
        def set_x_grid(self, x_min, x_max, x_step):
                """!
@@ -151,10 +161,12 @@
                @param x_max the right-most value
                @param x_step the grid spacing
                """
+               self.semaphore.acquire(True)
                self.x_min = float(x_min)
                self.x_max = float(x_max)
                self.x_step = float(x_step)
                self._changed = True
+               self.semaphore.release()
                
        def set_y_grid(self, y_min, y_max, y_step):
                """!
@@ -163,15 +175,18 @@
                @param y_max the top-most value
                @param y_step the grid spacing
                """
+               self.semaphore.acquire(True)
                self.y_min = float(y_min)
                self.y_max = float(y_max)
                self.y_step = float(y_step)
                self._changed = True
+               self.semaphore.release()
        
        def draw(self):
                """!
                Draw the grid and waveforms.
                """
+               self.semaphore.acquire(True)
                self.clear()
                #store the grid drawing operations
                if self._changed:
@@ -184,6 +199,7 @@
                glCallList(self.grid_compiled_list_id)
                glFlush()
                self.SwapBuffers()
+               self.semaphore.release()
        
        def _draw_waveforms(self):
                """!
@@ -233,17 +249,6 @@
                glEnd()
                
                ##################################################
-               # Draw Outter Border
-               ##################################################
-               glColor3f(*GRID_LINE_COLOR_SPEC)
-               glBegin(GL_LINE_LOOP)
-               glVertex3f(1, 1, 0)
-               glVertex3f(self.width, 1, 0)
-               glVertex3f(self.width, self.height, 0)
-               glVertex3f(1, self.height, 0)
-               glEnd()
-               
-               ##################################################
                # Draw Grid X
                ##################################################
                for tick in self._get_ticks(self.x_min, self.x_max, 
self.x_step):
@@ -285,10 +290,18 @@
                font.SetWeight(wx.FONTWEIGHT_BOLD)      
                #draw x units
                txt = gltext.Text(self.x_units, font=font, 
font_size=UNITS_TEXT_FONT_SIZE, centered=True)
-               txt.draw_text(wx.Point(self.width/2.0, 
self.height-.25*self.padding_bottom))
+               txt.draw_text(wx.Point(
+                               
(self.width-self.padding_left-self.padding_right)/2.0 + self.padding_left, 
+                               self.height-.25*self.padding_bottom,
+                               )
+               )
                #draw y units
                txt = gltext.Text(self.y_units, font=font, 
font_size=UNITS_TEXT_FONT_SIZE, centered=True)
-               txt.draw_text(wx.Point(.25*self.padding_left, self.height/2.0), 
rotation=90)
+               txt.draw_text(wx.Point(
+                               .25*self.padding_left, 
+                               
(self.height-self.padding_top-self.padding_bottom)/2.0 + self.padding_top,
+                       ), rotation=90,
+               )
                
                ##################################################
                # Draw Legend

Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py       
2008-07-01 00:26:53 UTC (rev 8757)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py       
2008-07-01 00:28:46 UTC (rev 8758)
@@ -26,10 +26,8 @@
 import plotter
 import common
 import wx
-import math
 import numpy
 import time
-import mutex
 
 ##################################################
 # Constants
@@ -73,7 +71,7 @@
                @param parent the wx parent window
                """
                self.parent = parent
-               wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER)     
+               wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)     
                control_box = wx.BoxSizer(wx.VERTICAL)
                
                #begin control box
@@ -235,7 +233,6 @@
                #check num inputs
                assert num_inputs <= len(CHANNEL_COLOR_SPECS)
                #setup
-               self.mutex = mutex.mutex()
                self.running = True
                self.num_inputs = num_inputs
                self.sample_rate = sample_rate
@@ -262,7 +259,7 @@
                self.frame_counter = 0
                self._init = False #HACK
                #init panel and plot 
-               wx.Panel.__init__(self, parent, -1)
+               wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER)
                self.plotter = plotter.grid_plotter(self)  
                self.plotter.SetSize(wx.Size(*size))
                self.plotter.set_title(title)
@@ -322,8 +319,7 @@
                        self.plotter.update()           
                self.frame_counter = (self.frame_counter + 1)%self.decim
                
-       def update(self): self.mutex.lock(self._update, None)   
-       def _update(self, arg=None):
+       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
@@ -353,8 +349,6 @@
                #update control panel and plotter
                self.control_panel.update()
                self.plotter.update()
-               #unlock mutex
-               self.mutex.unlock()
                
        ##################################################
        # Set parameters on-the-fly
@@ -417,8 +411,7 @@
                t_scale=None, 
                num_inputs=1,
                ac_couple=False,
-       ): 
-               self.num_inputs = num_inputs
+       ):
                #init
                gr.hier_block2.__init__(
                        self, 





reply via email to

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