summaryrefslogtreecommitdiff
path: root/gr-blocks/python
diff options
context:
space:
mode:
authorSebastian Koslowski <koslowski@kit.edu>2016-02-13 21:45:21 +0100
committerSebastian Koslowski <koslowski@kit.edu>2016-04-05 14:44:29 +0200
commit1d9143b0dbbaba502631326dd42d0bad1290ff93 (patch)
treeaff9ac49434f4a10bcd3d0509d4c3ed9a218aee8 /gr-blocks/python
parentfc05698ba1c292a3185ccff26f730320d7d27de6 (diff)
grc: move blks2 code into gr-blocks and gr-digital
Diffstat (limited to 'gr-blocks/python')
-rw-r--r--gr-blocks/python/grc_gnuradio/CMakeLists.txt37
-rw-r--r--gr-blocks/python/grc_gnuradio/README11
-rw-r--r--gr-blocks/python/grc_gnuradio/__init__.py1
-rw-r--r--gr-blocks/python/grc_gnuradio/blks2/__init__.py30
-rw-r--r--gr-blocks/python/grc_gnuradio/blks2/error_rate.py140
-rw-r--r--gr-blocks/python/grc_gnuradio/blks2/selector.py142
-rw-r--r--gr-blocks/python/grc_gnuradio/blks2/tcp.py70
7 files changed, 431 insertions, 0 deletions
diff --git a/gr-blocks/python/grc_gnuradio/CMakeLists.txt b/gr-blocks/python/grc_gnuradio/CMakeLists.txt
new file mode 100644
index 0000000000..9ff1240997
--- /dev/null
+++ b/gr-blocks/python/grc_gnuradio/CMakeLists.txt
@@ -0,0 +1,37 @@
+# Copyright 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
+ DESTINATION ${GR_PYTHON_DIR}/grc_gnuradio
+ COMPONENT "blocks_python"
+)
+
+GR_PYTHON_INSTALL(FILES
+ blks2/__init__.py
+ blks2/error_rate.py
+ blks2/selector.py
+ blks2/tcp.py
+ DESTINATION ${GR_PYTHON_DIR}/grc_gnuradio/blks2
+ COMPONENT "blocks_python"
+)
diff --git a/gr-blocks/python/grc_gnuradio/README b/gr-blocks/python/grc_gnuradio/README
new file mode 100644
index 0000000000..897eed65ca
--- /dev/null
+++ b/gr-blocks/python/grc_gnuradio/README
@@ -0,0 +1,11 @@
+This is the grc_gnuradio module.
+It contains supplemental python modules that grc uses at runtime.
+The supplemental modules are meant to mimic modules in gnuradio.
+These will be phased-out as new functionaility is merged into gnuradio.
+
+The blk2s module wraps many blocks in blks2 and gives them streaming outputs.
+Will be phased-out by new message passing implementations.
+Other blks2 blocks will hopefully make their way into blks2impl.
+
+The wxgui module contains a top_block + wxgui frame.
+Will be phased-out by gui.py in wxgui and a new top block template.
diff --git a/gr-blocks/python/grc_gnuradio/__init__.py b/gr-blocks/python/grc_gnuradio/__init__.py
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/gr-blocks/python/grc_gnuradio/__init__.py
@@ -0,0 +1 @@
+
diff --git a/gr-blocks/python/grc_gnuradio/blks2/__init__.py b/gr-blocks/python/grc_gnuradio/blks2/__init__.py
new file mode 100644
index 0000000000..d3c8210834
--- /dev/null
+++ b/gr-blocks/python/grc_gnuradio/blks2/__init__.py
@@ -0,0 +1,30 @@
+# Copyright 2008-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.
+#
+
+from selector import selector, valve
+from error_rate import error_rate
+from tcp import tcp_source, tcp_sink
+
+try:
+ from packet import options, packet_encoder, packet_decoder, \
+ packet_mod_b, packet_mod_s, packet_mod_i, packet_mod_f, packet_mod_c, \
+ packet_demod_b, packet_demod_s, packet_demod_i, packet_demod_f, packet_demod_c
+except ImportError:
+ pass # only available if gr-digital is install
diff --git a/gr-blocks/python/grc_gnuradio/blks2/error_rate.py b/gr-blocks/python/grc_gnuradio/blks2/error_rate.py
new file mode 100644
index 0000000000..9bf387030a
--- /dev/null
+++ b/gr-blocks/python/grc_gnuradio/blks2/error_rate.py
@@ -0,0 +1,140 @@
+# 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.
+#
+
+default_win_size = 1000
+
+from gnuradio import gr
+from gnuradio import blocks
+import gnuradio.gr.gr_threading as _threading
+import numpy
+
+#generate 1s counts array
+_1s_counts = [sum([1&(i>>j) for j in range(8)]) for i in range(2**8)]
+
+class input_watcher(_threading.Thread):
+ """
+ Read samples from the message queue and hand them to the callback.
+ """
+
+ def __init__(self, msgq, callback):
+ self._msgq = msgq
+ self._callback = callback
+ _threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.keep_running = True
+ self.start()
+
+ def run(self):
+ r = ''
+ while True:
+ msg = self._msgq.delete_head()
+ itemsize = int(msg.arg1())
+ nitems = int(msg.arg2())
+ s = r + msg.to_string()
+ i = (nitems-nitems%2)*itemsize
+ r = s[i:]
+ s = s[:i]
+ samples = numpy.fromstring(s, numpy.int8)
+ self._callback(samples)
+
+class error_rate(gr.hier_block2):
+ """
+ Sample the incoming data streams (byte) and calculate the bit or symbol error rate.
+ Write the running rate to the output data stream (float).
+ """
+
+ def __init__(self, type='BER', win_size=default_win_size, bits_per_symbol=2):
+ """
+ Error rate constructor.
+
+ Args:
+ type: a string 'BER' or 'SER'
+ win_size: the number of samples to calculate over
+ bits_per_symbol: the number of information bits per symbol (BER only)
+ """
+ #init
+ gr.hier_block2.__init__(
+ self, 'error_rate',
+ gr.io_signature(2, 2, gr.sizeof_char),
+ gr.io_signature(1, 1, gr.sizeof_float),
+ )
+ assert type in ('BER', 'SER')
+ self._max_samples = win_size
+ self._bits_per_symbol = bits_per_symbol
+ #setup message queue
+ msg_source = blocks.message_source(gr.sizeof_float, 1)
+ self._msgq_source = msg_source.msgq()
+ msgq_sink = gr.msg_queue(2)
+ msg_sink = blocks.message_sink(gr.sizeof_char, msgq_sink, False) #False -> blocking
+ inter = blocks.interleave(gr.sizeof_char)
+ #start thread
+ self._num_errs = 0
+ self._err_index = 0
+ self._num_samps = 0
+ self._err_array = numpy.zeros(self._max_samples, numpy.int8)
+ if type == 'BER':
+ input_watcher(msgq_sink, self._handler_ber)
+ elif type == 'SER':
+ input_watcher(msgq_sink, self._handler_ser)
+ #connect
+ self.connect(msg_source, self)
+ self.connect((self, 0), (inter, 0))
+ self.connect((self, 1), (inter, 1))
+ self.connect(inter, msg_sink)
+
+ def _handler_ber(self, samples):
+ num = len(samples)/2
+ arr = numpy.zeros(num, numpy.float32)
+ for i in range(num):
+ old_err = self._err_array[self._err_index]
+ #record error
+ self._err_array[self._err_index] = _1s_counts[samples[i*2] ^ samples[i*2 + 1]]
+ self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err
+ #increment index
+ self._err_index = (self._err_index + 1)%self._max_samples
+ self._num_samps = min(self._num_samps + 1, self._max_samples)
+ #write sample
+ arr[i] = float(self._num_errs)/float(self._num_samps*self._bits_per_symbol)
+ #write message
+ msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num)
+ self._msgq_source.insert_tail(msg)
+
+ def _handler_ser(self, samples):
+ num = len(samples)/2
+ arr = numpy.zeros(num, numpy.float32)
+ for i in range(num):
+ old_err = self._err_array[self._err_index]
+ #record error
+ ref = samples[i*2]
+ res = samples[i*2 + 1]
+ if ref == res:
+ self._err_array[self._err_index] = 0
+ else:
+ self._err_array[self._err_index] = 1
+ #update number of errors
+ self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err
+ #increment index
+ self._err_index = (self._err_index + 1)%self._max_samples
+ self._num_samps = min(self._num_samps + 1, self._max_samples)
+ #write sample
+ arr[i] = float(self._num_errs)/float(self._num_samps)
+ #write message
+ msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num)
+ self._msgq_source.insert_tail(msg)
diff --git a/gr-blocks/python/grc_gnuradio/blks2/selector.py b/gr-blocks/python/grc_gnuradio/blks2/selector.py
new file mode 100644
index 0000000000..24e3844658
--- /dev/null
+++ b/gr-blocks/python/grc_gnuradio/blks2/selector.py
@@ -0,0 +1,142 @@
+#
+# Copyright 2008,2013 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.
+#
+
+from gnuradio import gr
+from gnuradio import blocks
+
+class selector(gr.hier_block2):
+ """A hier2 block with N inputs and M outputs, where data is only forwarded through input n to output m."""
+ def __init__(self, item_size, num_inputs, num_outputs, input_index, output_index):
+ """
+ Selector constructor.
+
+ Args:
+ item_size: the size of the gr data stream in bytes
+ num_inputs: the number of inputs (integer)
+ num_outputs: the number of outputs (integer)
+ input_index: the index for the source data
+ output_index: the index for the destination data
+ """
+ gr.hier_block2.__init__(
+ self, 'selector',
+ gr.io_signature(num_inputs, num_inputs, item_size),
+ gr.io_signature(num_outputs, num_outputs, item_size),
+ )
+ #terminator blocks for unused inputs and outputs
+ self.input_terminators = [blocks.null_sink(item_size) for i in range(num_inputs)]
+ self.output_terminators = [blocks.head(item_size, 0) for i in range(num_outputs)]
+ self.copy = blocks.copy(item_size)
+ #connections
+ for i in range(num_inputs): self.connect((self, i), self.input_terminators[i])
+ for i in range(num_outputs): self.connect(blocks.null_source(item_size),
+ self.output_terminators[i], (self, i))
+ self.item_size = item_size
+ self.input_index = input_index
+ self.output_index = output_index
+ self.num_inputs = num_inputs
+ self.num_outputs = num_outputs
+ self._connect_current()
+
+ def _indexes_valid(self):
+ """
+ Are the input and output indexes within range of the number of inputs and outputs?
+
+ Returns:
+ true if input index and output index are in range
+ """
+ return self.input_index in range(self.num_inputs) and self.output_index in range(self.num_outputs)
+
+ def _connect_current(self):
+ """If the input and output indexes are valid:
+ disconnect the blocks at the input and output index from their terminators,
+ and connect them to one another. Then connect the terminators to one another."""
+ if self._indexes_valid():
+ self.disconnect((self, self.input_index), self.input_terminators[self.input_index])
+ self.disconnect(self.output_terminators[self.output_index], (self, self.output_index))
+ self.connect((self, self.input_index), self.copy)
+ self.connect(self.copy, (self, self.output_index))
+ self.connect(self.output_terminators[self.output_index], self.input_terminators[self.input_index])
+
+ def _disconnect_current(self):
+ """If the input and output indexes are valid:
+ disconnect the blocks at the input and output index from one another,
+ and the terminators at the input and output index from one another.
+ Reconnect the blocks to the terminators."""
+ if self._indexes_valid():
+ self.disconnect((self, self.input_index), self.copy)
+ self.disconnect(self.copy, (self, self.output_index))
+ self.disconnect(self.output_terminators[self.output_index], self.input_terminators[self.input_index])
+ self.connect((self, self.input_index), self.input_terminators[self.input_index])
+ self.connect(self.output_terminators[self.output_index], (self, self.output_index))
+
+ def set_input_index(self, input_index):
+ """
+ Change the block to the new input index if the index changed.
+
+ Args:
+ input_index: the new input index
+ """
+ if self.input_index != input_index:
+ self.lock()
+ self._disconnect_current()
+ self.input_index = input_index
+ self._connect_current()
+ self.unlock()
+
+ def set_output_index(self, output_index):
+ """
+ Change the block to the new output index if the index changed.
+
+ Args:
+ output_index: the new output index
+ """
+ if self.output_index != output_index:
+ self.lock()
+ self._disconnect_current()
+ self.output_index = output_index
+ self._connect_current()
+ self.unlock()
+
+class valve(selector):
+ """Wrapper for selector with 1 input and 1 output."""
+
+ def __init__(self, item_size, open):
+ """
+ Constructor for valve.
+
+ Args:
+ item_size: the size of the gr data stream in bytes
+ open: true if initial valve state is open
+ """
+ if open: output_index = -1
+ else: output_index = 0
+ selector.__init__(self, item_size, 1, 1, 0, output_index)
+
+ def set_open(self, open):
+ """
+ Callback to set open state.
+
+ Args:
+ open: true to set valve state to open
+ """
+ if open: output_index = -1
+ else: output_index = 0
+ self.set_output_index(output_index)
diff --git a/gr-blocks/python/grc_gnuradio/blks2/tcp.py b/gr-blocks/python/grc_gnuradio/blks2/tcp.py
new file mode 100644
index 0000000000..aee90fad2c
--- /dev/null
+++ b/gr-blocks/python/grc_gnuradio/blks2/tcp.py
@@ -0,0 +1,70 @@
+#
+# 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.
+#
+
+from gnuradio import gr, blocks
+import socket
+import os
+
+def _get_sock_fd(addr, port, server):
+ """
+ Get the file descriptor for the socket.
+ As a client, block on connect, dup the socket descriptor.
+ As a server, block on accept, dup the client descriptor.
+
+ Args:
+ addr: the ip address string
+ port: the tcp port number
+ server: true for server mode, false for client mode
+
+ Returns:
+ the file descriptor number
+ """
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ if server:
+ sock.bind((addr, port))
+ sock.listen(1)
+ clientsock, address = sock.accept()
+ return os.dup(clientsock.fileno())
+ else:
+ sock.connect((addr, port))
+ return os.dup(sock.fileno())
+
+class tcp_source(gr.hier_block2):
+ def __init__(self, itemsize, addr, port, server=True):
+ #init hier block
+ gr.hier_block2.__init__(
+ self, 'tcp_source',
+ gr.io_signature(0, 0, 0),
+ gr.io_signature(1, 1, itemsize),
+ )
+ fd = _get_sock_fd(addr, port, server)
+ self.connect(blocks.file_descriptor_source(itemsize, fd), self)
+
+class tcp_sink(gr.hier_block2):
+ def __init__(self, itemsize, addr, port, server=False):
+ #init hier block
+ gr.hier_block2.__init__(
+ self, 'tcp_sink',
+ gr.io_signature(1, 1, itemsize),
+ gr.io_signature(0, 0, 0),
+ )
+ fd = _get_sock_fd(addr, port, server)
+ self.connect(self, blocks.file_descriptor_sink(itemsize, fd))