summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/python/gnuradio/gru
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-runtime/python/gnuradio/gru')
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/CMakeLists.txt36
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/__init__.py13
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/daemon.py102
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/freqz.py344
-rwxr-xr-xgnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py102
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/hexint.py44
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/listmisc.py29
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/mathmisc.py33
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/msgq_runner.py82
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py36
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py77
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/socket_stuff.py62
12 files changed, 960 insertions, 0 deletions
diff --git a/gnuradio-runtime/python/gnuradio/gru/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/gru/CMakeLists.txt
new file mode 100644
index 0000000000..c147981472
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/CMakeLists.txt
@@ -0,0 +1,36 @@
+# Copyright 2010-2011 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.
+
+include(GrPython)
+
+GR_PYTHON_INSTALL(FILES
+ __init__.py
+ freqz.py
+ gnuplot_freqz.py
+ hexint.py
+ listmisc.py
+ mathmisc.py
+ msgq_runner.py
+ os_read_exactly.py
+ seq_with_cursor.py
+ socket_stuff.py
+ daemon.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/gru
+ COMPONENT "core_python"
+)
diff --git a/gnuradio-runtime/python/gnuradio/gru/__init__.py b/gnuradio-runtime/python/gnuradio/gru/__init__.py
new file mode 100644
index 0000000000..4e41d03a74
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/__init__.py
@@ -0,0 +1,13 @@
+# make this a package
+
+# Import gru stuff
+from daemon import *
+from freqz import *
+from gnuplot_freqz import *
+from hexint import *
+from listmisc import *
+from mathmisc import *
+from msgq_runner import *
+from os_read_exactly import *
+from seq_with_cursor import *
+from socket_stuff import *
diff --git a/gnuradio-runtime/python/gnuradio/gru/daemon.py b/gnuradio-runtime/python/gnuradio/gru/daemon.py
new file mode 100644
index 0000000000..e04702152d
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/daemon.py
@@ -0,0 +1,102 @@
+#
+# 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.
+#
+import os, sys, signal
+
+# Turn application into a background daemon process.
+#
+# When this function returns:
+#
+# 1) The calling process is disconnected from its controlling terminal
+# and will not exit when the controlling session exits
+# 2) If a pidfile name is provided, it is created and the new pid is
+# written into it.
+# 3) If a logfile name is provided, it is opened and stdout/stderr are
+# redirected to it.
+# 4) The process current working directory is changed to '/' to avoid
+# pinning any filesystem mounts.
+# 5) The process umask is set to 0111.
+#
+# The return value is the new pid.
+#
+# To create GNU Radio applications that operate as daemons, add a call to this
+# function after all initialization but just before calling gr.top_block.run()
+# or .start().
+#
+# Daemonized GNU Radio applications may be stopped by sending them a
+# SIGINT, SIGKILL, or SIGTERM, e.g., using 'kill pid' from the command line.
+#
+# If your application uses gr.top_block.run(), the flowgraph will be stopped
+# and the function will return. You should allow your daemon program to exit
+# at this point.
+#
+# If your application uses gr.top_block.start(), you are responsible for hooking
+# the Python signal handler (see 'signal' module) and calling gr.top_block.stop()
+# on your top block, and otherwise causing your daemon process to exit.
+#
+
+def daemonize(pidfile=None, logfile=None):
+ # fork() into background
+ try:
+ pid = os.fork()
+ except OSError, e:
+ raise Exception, "%s [%d]" % (e.strerror, e.errno)
+
+ if pid == 0: # First child of first fork()
+ # Become session leader of new session
+ os.setsid()
+
+ # fork() into background again
+ try:
+ pid = os.fork()
+ except OSError, e:
+ raise Exception, "%s [%d]" % (e.strerror, e.errno)
+
+ if pid != 0:
+ os._exit(0) # Second child of second fork()
+
+ else: # Second child of first fork()
+ os._exit(0)
+
+ os.umask(0111)
+
+ # Write pid
+ pid = os.getpid()
+ if pidfile is not None:
+ open(pidfile, 'w').write('%d\n'%pid)
+
+ # Redirect streams
+ if logfile is not None:
+ lf = open(logfile, 'a+')
+ sys.stdout = lf
+ sys.stderr = lf
+
+ # Prevent pinning any filesystem mounts
+ os.chdir('/')
+
+ # Tell caller what pid to send future signals to
+ return pid
+
+if __name__ == "__main__":
+ import time
+ daemonize()
+ print "Hello, world, from daemon process."
+ time.sleep(20)
+ print "Goodbye, world, from daemon process."
diff --git a/gnuradio-runtime/python/gnuradio/gru/freqz.py b/gnuradio-runtime/python/gnuradio/gru/freqz.py
new file mode 100644
index 0000000000..60dca64a58
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/freqz.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,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.
+#
+
+# This code lifted from various parts of www.scipy.org -eb 2005-01-24
+
+# Copyright (c) 2001, 2002 Enthought, Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# a. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# b. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# c. Neither the name of the Enthought nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+#
+
+__all__ = ['freqz']
+
+import numpy
+from numpy import *
+Num=numpy
+
+def atleast_1d(*arys):
+ """ Force a sequence of arrays to each be at least 1D.
+
+ Description:
+ Force an array to be at least 1D. If an array is 0D, the
+ array is converted to a single row of values. Otherwise,
+ the array is unaltered.
+ Arguments:
+ *arys -- arrays to be converted to 1 or more dimensional array.
+ Returns:
+ input array converted to at least 1D array.
+ """
+ res = []
+ for ary in arys:
+ ary = asarray(ary)
+ if len(ary.shape) == 0:
+ result = numpy.array([ary[0]])
+ else:
+ result = ary
+ res.append(result)
+ if len(res) == 1:
+ return res[0]
+ else:
+ return res
+
+
+def polyval(p,x):
+ """Evaluate the polynomial p at x. If x is a polynomial then composition.
+
+ Description:
+
+ If p is of length N, this function returns the value:
+ p[0]*(x**N-1) + p[1]*(x**N-2) + ... + p[N-2]*x + p[N-1]
+
+ x can be a sequence and p(x) will be returned for all elements of x.
+ or x can be another polynomial and the composite polynomial p(x) will be
+ returned.
+ """
+ p = asarray(p)
+ if isinstance(x,poly1d):
+ y = 0
+ else:
+ x = asarray(x)
+ y = numpy.zeros(x.shape,x.typecode())
+ for i in range(len(p)):
+ y = x * y + p[i]
+ return y
+
+class poly1d:
+ """A one-dimensional polynomial class.
+
+ p = poly1d([1,2,3]) constructs the polynomial x**2 + 2 x + 3
+
+ p(0.5) evaluates the polynomial at the location
+ p.r is a list of roots
+ p.c is the coefficient array [1,2,3]
+ p.order is the polynomial order (after leading zeros in p.c are removed)
+ p[k] is the coefficient on the kth power of x (backwards from
+ sequencing the coefficient array.
+
+ polynomials can be added, substracted, multplied and divided (returns
+ quotient and remainder).
+ asarray(p) will also give the coefficient array, so polynomials can
+ be used in all functions that accept arrays.
+ """
+ def __init__(self, c_or_r, r=0):
+ if isinstance(c_or_r,poly1d):
+ for key in c_or_r.__dict__.keys():
+ self.__dict__[key] = c_or_r.__dict__[key]
+ return
+ if r:
+ c_or_r = poly(c_or_r)
+ c_or_r = atleast_1d(c_or_r)
+ if len(c_or_r.shape) > 1:
+ raise ValueError, "Polynomial must be 1d only."
+ c_or_r = trim_zeros(c_or_r, trim='f')
+ if len(c_or_r) == 0:
+ c_or_r = numpy.array([0])
+ self.__dict__['coeffs'] = c_or_r
+ self.__dict__['order'] = len(c_or_r) - 1
+
+ def __array__(self,t=None):
+ if t:
+ return asarray(self.coeffs,t)
+ else:
+ return asarray(self.coeffs)
+
+ def __coerce__(self,other):
+ return None
+
+ def __repr__(self):
+ vals = repr(self.coeffs)
+ vals = vals[6:-1]
+ return "poly1d(%s)" % vals
+
+ def __len__(self):
+ return self.order
+
+ def __str__(self):
+ N = self.order
+ thestr = "0"
+ for k in range(len(self.coeffs)):
+ coefstr ='%.4g' % abs(self.coeffs[k])
+ if coefstr[-4:] == '0000':
+ coefstr = coefstr[:-5]
+ power = (N-k)
+ if power == 0:
+ if coefstr != '0':
+ newstr = '%s' % (coefstr,)
+ else:
+ if k == 0:
+ newstr = '0'
+ else:
+ newstr = ''
+ elif power == 1:
+ if coefstr == '0':
+ newstr = ''
+ elif coefstr == '1':
+ newstr = 'x'
+ else:
+ newstr = '%s x' % (coefstr,)
+ else:
+ if coefstr == '0':
+ newstr = ''
+ elif coefstr == '1':
+ newstr = 'x**%d' % (power,)
+ else:
+ newstr = '%s x**%d' % (coefstr, power)
+
+ if k > 0:
+ if newstr != '':
+ if self.coeffs[k] < 0:
+ thestr = "%s - %s" % (thestr, newstr)
+ else:
+ thestr = "%s + %s" % (thestr, newstr)
+ elif (k == 0) and (newstr != '') and (self.coeffs[k] < 0):
+ thestr = "-%s" % (newstr,)
+ else:
+ thestr = newstr
+ return _raise_power(thestr)
+
+
+ def __call__(self, val):
+ return polyval(self.coeffs, val)
+
+ def __mul__(self, other):
+ if isscalar(other):
+ return poly1d(self.coeffs * other)
+ else:
+ other = poly1d(other)
+ return poly1d(polymul(self.coeffs, other.coeffs))
+
+ def __rmul__(self, other):
+ if isscalar(other):
+ return poly1d(other * self.coeffs)
+ else:
+ other = poly1d(other)
+ return poly1d(polymul(self.coeffs, other.coeffs))
+
+ def __add__(self, other):
+ other = poly1d(other)
+ return poly1d(polyadd(self.coeffs, other.coeffs))
+
+ def __radd__(self, other):
+ other = poly1d(other)
+ return poly1d(polyadd(self.coeffs, other.coeffs))
+
+ def __pow__(self, val):
+ if not isscalar(val) or int(val) != val or val < 0:
+ raise ValueError, "Power to non-negative integers only."
+ res = [1]
+ for k in range(val):
+ res = polymul(self.coeffs, res)
+ return poly1d(res)
+
+ def __sub__(self, other):
+ other = poly1d(other)
+ return poly1d(polysub(self.coeffs, other.coeffs))
+
+ def __rsub__(self, other):
+ other = poly1d(other)
+ return poly1d(polysub(other.coeffs, self.coeffs))
+
+ def __div__(self, other):
+ if isscalar(other):
+ return poly1d(self.coeffs/other)
+ else:
+ other = poly1d(other)
+ return map(poly1d,polydiv(self.coeffs, other.coeffs))
+
+ def __rdiv__(self, other):
+ if isscalar(other):
+ return poly1d(other/self.coeffs)
+ else:
+ other = poly1d(other)
+ return map(poly1d,polydiv(other.coeffs, self.coeffs))
+
+ def __setattr__(self, key, val):
+ raise ValueError, "Attributes cannot be changed this way."
+
+ def __getattr__(self, key):
+ if key in ['r','roots']:
+ return roots(self.coeffs)
+ elif key in ['c','coef','coefficients']:
+ return self.coeffs
+ elif key in ['o']:
+ return self.order
+ else:
+ return self.__dict__[key]
+
+ def __getitem__(self, val):
+ ind = self.order - val
+ if val > self.order:
+ return 0
+ if val < 0:
+ return 0
+ return self.coeffs[ind]
+
+ def __setitem__(self, key, val):
+ ind = self.order - key
+ if key < 0:
+ raise ValueError, "Does not support negative powers."
+ if key > self.order:
+ zr = numpy.zeros(key-self.order,self.coeffs.typecode())
+ self.__dict__['coeffs'] = numpy.concatenate((zr,self.coeffs))
+ self.__dict__['order'] = key
+ ind = 0
+ self.__dict__['coeffs'][ind] = val
+ return
+
+ def integ(self, m=1, k=0):
+ return poly1d(polyint(self.coeffs,m=m,k=k))
+
+ def deriv(self, m=1):
+ return poly1d(polyder(self.coeffs,m=m))
+
+def freqz(b, a, worN=None, whole=0, plot=None):
+ """Compute frequency response of a digital filter.
+
+ Description:
+
+ Given the numerator (b) and denominator (a) of a digital filter compute
+ its frequency response.
+
+ jw -jw -jmw
+ jw B(e) b[0] + b[1]e + .... + b[m]e
+ H(e) = ---- = ------------------------------------
+ jw -jw -jnw
+ A(e) a[0] + a[2]e + .... + a[n]e
+
+ Inputs:
+
+ b, a --- the numerator and denominator of a linear filter.
+ worN --- If None, then compute at 512 frequencies around the unit circle.
+ If a single integer, the compute at that many frequencies.
+ Otherwise, compute the response at frequencies given in worN
+ whole -- Normally, frequencies are computed from 0 to pi (upper-half of
+ unit-circle. If whole is non-zero compute frequencies from 0
+ to 2*pi.
+
+ Outputs: (h,w)
+
+ h -- The frequency response.
+ w -- The frequencies at which h was computed.
+ """
+ b, a = map(atleast_1d, (b,a))
+ if whole:
+ lastpoint = 2*pi
+ else:
+ lastpoint = pi
+ if worN is None:
+ N = 512
+ w = Num.arange(0,lastpoint,lastpoint/N)
+ elif isinstance(worN, types.IntType):
+ N = worN
+ w = Num.arange(0,lastpoint,lastpoint/N)
+ else:
+ w = worN
+ w = atleast_1d(w)
+ zm1 = exp(-1j*w)
+ h = polyval(b[::-1], zm1) / polyval(a[::-1], zm1)
+ # if not plot is None:
+ # plot(w, h)
+ return h, w
diff --git a/gnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py b/gnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py
new file mode 100755
index 0000000000..dd483e4277
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,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.
+#
+
+__all__ = ['gnuplot_freqz']
+
+import tempfile
+import os
+import math
+import numpy
+
+from gnuradio import gr
+from gnuradio.gru.freqz import freqz
+
+
+def gnuplot_freqz (hw, Fs=None, logfreq=False):
+
+ """hw is a tuple of the form (h, w) where h is sequence of complex
+ freq responses, and w is a sequence of corresponding frequency
+ points. Plot the frequency response using gnuplot. If Fs is
+ provide, use it as the sampling frequency, else use 2*pi.
+
+ Returns a handle to the gnuplot graph. When the handle is reclaimed
+ the graph is torn down."""
+
+ data_file = tempfile.NamedTemporaryFile ()
+ cmd_file = os.popen ('gnuplot', 'w')
+
+ h, w = hw
+ ampl = 20 * numpy.log10 (numpy.absolute (h) + 1e-9)
+ phase = map (lambda x: math.atan2 (x.imag, x.real), h)
+
+ if Fs:
+ w *= (Fs/(2*math.pi))
+
+ for freq, a, ph in zip (w, ampl, phase):
+ data_file.write ("%g\t%g\t%g\n" % (freq, a, ph))
+
+ data_file.flush ()
+
+ cmd_file.write ("set grid\n")
+ if logfreq:
+ cmd_file.write ("set logscale x\n")
+ else:
+ cmd_file.write ("unset logscale x\n")
+ cmd_file.write ("plot '%s' using 1:2 with lines\n" % (data_file.name,))
+ cmd_file.flush ()
+
+ return (cmd_file, data_file)
+
+
+def test_plot ():
+ sample_rate = 2.0e6
+ #taps = firdes.low_pass(1, sample_rate, 200000, 100000, firdes.WIN_HAMMING)
+ taps = (0.0007329441141337156, 0.0007755281985737383, 0.0005323155201040208,
+ -7.679847761841656e-19, -0.0007277769618667662, -0.001415981911122799,
+ -0.0017135187517851591, -0.001282231998629868, 1.61239866282397e-18,
+ 0.0018589380197227001, 0.0035909228026866913, 0.004260237794369459,
+ 0.00310456077568233, -3.0331308923229716e-18, -0.004244099836796522,
+ -0.007970594801008701, -0.009214458055794239, -0.006562007591128349,
+ 4.714311174044374e-18, 0.008654761128127575, 0.01605774275958538,
+ 0.01841980405151844, 0.013079923577606678, -6.2821650235090215e-18,
+ -0.017465557903051376, -0.032989680767059326, -0.03894065320491791,
+ -0.028868533670902252, 7.388111706347014e-18, 0.04517475143074989,
+ 0.09890196472406387, 0.14991308748722076, 0.18646684288978577,
+ 0.19974154233932495, 0.18646684288978577, 0.14991308748722076,
+ 0.09890196472406387, 0.04517475143074989, 7.388111706347014e-18,
+ -0.028868533670902252, -0.03894065320491791, -0.032989680767059326,
+ -0.017465557903051376, -6.2821650235090215e-18, 0.013079923577606678,
+ 0.01841980405151844, 0.01605774275958538, 0.008654761128127575,
+ 4.714311174044374e-18, -0.006562007591128349, -0.009214458055794239,
+ -0.007970594801008701, -0.004244099836796522, -3.0331308923229716e-18,
+ 0.00310456077568233, 0.004260237794369459, 0.0035909228026866913,
+ 0.0018589380197227001, 1.61239866282397e-18, -0.001282231998629868,
+ -0.0017135187517851591, -0.001415981911122799, -0.0007277769618667662,
+ -7.679847761841656e-19, 0.0005323155201040208, 0.0007755281985737383,
+ 0.0007329441141337156)
+
+ # print len (taps)
+ return gnuplot_freqz (freqz (taps, 1), sample_rate)
+
+if __name__ == '__main__':
+ handle = test_plot ()
+ raw_input ('Press Enter to continue: ')
diff --git a/gnuradio-runtime/python/gnuradio/gru/hexint.py b/gnuradio-runtime/python/gnuradio/gru/hexint.py
new file mode 100644
index 0000000000..0fb5ecde04
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/hexint.py
@@ -0,0 +1,44 @@
+#
+# Copyright 2005 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.
+#
+
+def hexint(mask):
+ """
+ Convert unsigned masks into signed ints.
+
+ This allows us to use hex constants like 0xf0f0f0f2 when talking to
+ our hardware and not get screwed by them getting treated as python
+ longs.
+ """
+ if mask >= 2**31:
+ return int(mask-2**32)
+ return mask
+
+def hexshort(mask):
+ """
+ Convert unsigned masks into signed shorts.
+
+ This allows us to use hex constants like 0x8000 when talking to
+ our hardware and not get screwed by them getting treated as python
+ longs.
+ """
+ if mask >= 2**15:
+ return int(mask-2**16)
+ return mask
diff --git a/gnuradio-runtime/python/gnuradio/gru/listmisc.py b/gnuradio-runtime/python/gnuradio/gru/listmisc.py
new file mode 100644
index 0000000000..9e70eb863c
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/listmisc.py
@@ -0,0 +1,29 @@
+#
+# Copyright 2005 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.
+#
+
+def list_reverse(x):
+ """
+ Return a copy of x that is reverse order.
+ """
+ r = list(x)
+ r.reverse()
+ return r
+
diff --git a/gnuradio-runtime/python/gnuradio/gru/mathmisc.py b/gnuradio-runtime/python/gnuradio/gru/mathmisc.py
new file mode 100644
index 0000000000..7e6f23a346
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/mathmisc.py
@@ -0,0 +1,33 @@
+#
+# Copyright 2005 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.
+#
+
+import math
+
+def gcd(a,b):
+ while b:
+ a,b = b, a % b
+ return a
+
+def lcm(a,b):
+ return a * b / gcd(a, b)
+
+def log2(x):
+ return math.log(x)/math.log(2)
diff --git a/gnuradio-runtime/python/gnuradio/gru/msgq_runner.py b/gnuradio-runtime/python/gnuradio/gru/msgq_runner.py
new file mode 100644
index 0000000000..767a74a717
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/msgq_runner.py
@@ -0,0 +1,82 @@
+#
+# Copyright 2009 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.
+#
+
+"""
+Convenience class for dequeuing messages from a gr.msg_queue and
+invoking a callback.
+
+Creates a Python thread that does a blocking read on the supplied
+gr.msg_queue, then invokes callback each time a msg is received.
+
+If the msg type is not 0, then it is treated as a signal to exit
+its loop.
+
+If the callback raises an exception, and the runner was created
+with 'exit_on_error' equal to True, then the runner will store the
+exception and exit its loop, otherwise the exception is ignored.
+
+To get the exception that the callback raised, if any, call
+exit_error() on the object.
+
+To manually stop the runner, call stop() on the object.
+
+To determine if the runner has exited, call exited() on the object.
+"""
+
+from gnuradio import gr
+import gnuradio.gr.gr_threading as _threading
+
+class msgq_runner(_threading.Thread):
+
+ def __init__(self, msgq, callback, exit_on_error=False):
+ _threading.Thread.__init__(self)
+
+ self._msgq = msgq
+ self._callback = callback
+ self._exit_on_error = exit_on_error
+ self._done = False
+ self._exited = False
+ self._exit_error = None
+ self.setDaemon(1)
+ self.start()
+
+ def run(self):
+ while not self._done:
+ msg = self._msgq.delete_head()
+ if msg.type() != 0:
+ self.stop()
+ else:
+ try:
+ self._callback(msg)
+ except Exception, e:
+ if self._exit_on_error:
+ self._exit_error = e
+ self.stop()
+ self._exited = True
+
+ def stop(self):
+ self._done = True
+
+ def exited(self):
+ return self._exited
+
+ def exit_error(self):
+ return self._exit_error
diff --git a/gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py b/gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py
new file mode 100644
index 0000000000..40b053770e
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py
@@ -0,0 +1,36 @@
+#
+# Copyright 2005 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.
+#
+
+import os
+
+def os_read_exactly(file_descriptor, nbytes):
+ """
+ Replacement for os.read that blocks until it reads exactly nbytes.
+
+ """
+ s = ''
+ while nbytes > 0:
+ sbuf = os.read(file_descriptor, nbytes)
+ if not(sbuf):
+ return ''
+ nbytes -= len(sbuf)
+ s = s + sbuf
+ return s
diff --git a/gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py b/gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py
new file mode 100644
index 0000000000..def3299b69
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py
@@ -0,0 +1,77 @@
+#
+# Copyright 2003,2004 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.
+#
+
+# misc utilities
+
+import types
+import exceptions
+
+class seq_with_cursor (object):
+ __slots__ = [ 'items', 'index' ]
+
+ def __init__ (self, items, initial_index = None, initial_value = None):
+ assert len (items) > 0, "seq_with_cursor: len (items) == 0"
+ self.items = items
+ self.set_index (initial_index)
+ if initial_value is not None:
+ self.set_index_by_value(initial_value)
+
+ def set_index (self, initial_index):
+ if initial_index is None:
+ self.index = len (self.items) / 2
+ elif initial_index >= 0 and initial_index < len (self.items):
+ self.index = initial_index
+ else:
+ raise exceptions.ValueError
+
+ def set_index_by_value(self, v):
+ """
+ Set index to the smallest value such that items[index] >= v.
+ If there is no such item, set index to the maximum value.
+ """
+ self.set_index(0) # side effect!
+ cv = self.current()
+ more = True
+ while cv < v and more:
+ cv, more = self.next() # side effect!
+
+ def next (self):
+ new_index = self.index + 1
+ if new_index < len (self.items):
+ self.index = new_index
+ return self.items[new_index], True
+ else:
+ return self.items[self.index], False
+
+ def prev (self):
+ new_index = self.index - 1
+ if new_index >= 0:
+ self.index = new_index
+ return self.items[new_index], True
+ else:
+ return self.items[self.index], False
+
+ def current (self):
+ return self.items[self.index]
+
+ def get_seq (self):
+ return self.items[:] # copy of items
+
diff --git a/gnuradio-runtime/python/gnuradio/gru/socket_stuff.py b/gnuradio-runtime/python/gnuradio/gru/socket_stuff.py
new file mode 100644
index 0000000000..489b6ab255
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/socket_stuff.py
@@ -0,0 +1,62 @@
+#
+# Copyright 2005 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.
+#
+
+# random socket related stuff
+
+import socket
+import os
+import sys
+
+def tcp_connect_or_die(sock_addr):
+ """
+
+ Args:
+ sock_addr: (host, port) to connect to (tuple)
+
+ Returns:
+ : socket or exits
+ """
+ s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
+ try:
+ s.connect(sock_addr)
+ except socket.error, err:
+ sys.stderr.write('Failed to connect to %s: %s\n' %
+ (sock_addr, os.strerror (err.args[0]),))
+ sys.exit(1)
+ return s
+
+def udp_connect_or_die(sock_addr):
+ """
+
+ Args:
+ sock_addr: (host, port) to connect to (tuple)
+
+ Returns:
+ : socket or exits
+ """
+ s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM)
+ try:
+ s.connect(sock_addr)
+ except socket.error, err:
+ sys.stderr.write('Failed to connect to %s: %s\n' %
+ (sock_addr, os.strerror (err.args[0]),))
+ sys.exit(1)
+ return s