You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The following are examples of different ways to work with custom GNU Radio blocks. The main functionality for blocks are contained in either Python or C++ with the graphical/input parameters configured in a .xml or .yml file depending on the GNU Radio version.
Copy gr-name folder to ~/Fissure/Custom_Blocks/maint-3.x and build the module. Afterwards, click the "Reload Blocks" arrow in GNU Radio Companion to load the new custom blocks.
cd *~/FISSURE/Custom_Blocks/maint-3.7/gr-<name>*
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfig
Refresh GNU Radio Companion
Click the blue arrow to reload the blocks.
Making C++ Blocks
gr_modtool add -t sync -l cpp <block_name>
Similar procedure to Python but use this for the complex data type:
importnumpyasnpfromgnuradioimportgrimportpmtclassblk(gr.sync_block):
def__init__(self):
gr.sync_block.__init__(
self,
name='Embedded Python Block',
in_sig=[np.complex64],
out_sig=[np.complex64]
)
defwork(self, input_items, output_items):
forindx, sampleinenumerate(input_items[0]):
ifnp.random.rand() >0.95: # 5% chance this sample is chosenkey=pmt.intern("example_key")
value=pmt.intern("example_value")
self.add_item_tag(0, self.nitems_written(0) +indx, key, value)
# note: (self.nitems_written(0) + indx) is our current sample, in absolute timeoutput_items[0][:] =input_items[0] # copy input to outputreturnlen(output_items[0])
Reading Stream Tags
To get tags from a particular input stream, we have two functions we can use:
gr::block::get_tags_in_range: Gets all tags from a particular input port between a certain range of items (in absolute item time).
gr::block::get_tags_in_window: Gets all tags from a particular input port between a certain range of items (in relative item time within the work function).
The difference between these functions is working in absolute item time versus relative item time. Both of these pass back vectors of gr::tag_t, and they both allow specifying a particular key (as a PMT symbol) to filter against (or the fifth argument can be left out to search for all keys). Filtering for a certain key reduces the effort inside the work function for getting the right tag's data.
For example, this call just returns any tags between the given range of items:
#include <pmt/pmt.h>
#include <string>
void get_tags_in_range(std::vector<tag_t> &v,
unsigned int which_input,
uint64_t abs_start,
uint64_t abs_end);
std::vector<gr::tag_t> tags;
get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0) + framesize);
for (unsigned t = 0; t < tags.size(); t++) {
int offset = tags[t].offset - nitems_read(0);
tags[t].offset = offset + nitems_written(0);
add_item_tag(0, tags[t]);
printf("\n[*] TAG FOUND: %s", (pmt::symbol_to_string(tags[t].key)).c_str());
Adding a fifth argument to this function allows us to filter on the key key.
In Python, the main difference from the C++ function is that instead of having the first argument be a vector where the tags are stored, the Python version just returns a list of tags. We would use it like this:
The history is the number of items a block needs to calculate 1 output item. For a filter, this is equal to the number of taps.
For a simple differentiator (y(n) = x(n) - x(n-1)), the history equals 2. Obviously, the smallest value for the history is 1.
When you are in the work function, the number of items in your input buffer equals the number of input items plus the history minus one.
Here is an example for an accumulator that outputs the sum of the last N items:
for (inti=0; i<noutput_items; i++) {
out[i] =0;
for (intk=0; k<history(); k++) {
out[i] +=in[i+k];
}
}
As you can see, noutput_items items of out[] are written, whereas noutput_items + history() - 1 items of in[] are read from.
If the history has the value N, the first N-1 items are "old" items, i.e. they were available in the previous call to work() (when work() is called the first time, they are set to zero).
Message Passing
Must register input, output ports when using "message" as a block output type:
self.message_port_register_in(pmt.intern("in_port_name"))
self.message_port_register_out(pmt.intern("out_port_name"))
self.set_msg_handler(pmt.intern("port name"), <msg handler function>)
self.set_msg_handler(pmt.intern("port name"), self.handle_msg) # No () and no input parameters
def handle_msg(self, msg):
snr = pmt.to_float(msg)
const pmt::pmt_t d_port; // in .h private:
d_port(pmt::mp("header_data")) // in impl before {}
message_port_register_out(d_port); // in impl in the {}
message_port_pub(d_port, pmt::PMT_F);
pmt::pmt_t dict(pmt::make_dict());
for (unsigned i = 0; i < tags.size(); i++) {
dict = pmt::dict_add(dict, tags[i].key, tags[i].value);
}
message_port_pub(d_port, dict);
message_port_pub(d_snr_port, pmt::from_float(snr_avg));
message_port_register_in(pmt::mp("print"));
set_msg_handler(pmt::mp("print"),
boost::bind(&message_debug_impl::print, this, _1));
void message_debug_impl::print(pmt::pmt_t msg)
{
std::cout << "***** MESSAGE DEBUG PRINT ********\n";
pmt::print(msg);
std::cout << "**********************************\n";
}
import zmq
from zmq import Again as ZMQ_sub_timeout
import numpy, pmt
import binascii
class ZMQ_sub(object):
def __init__(self, portIn, timeout = 100):
self._ipAddress = '127.0.0.1'
self._portIn = portIn
self._zmqContext = zmq.Context()
self._socketIn = self._zmqContext.socket(zmq.SUB)
self._socketIn.RCVTIMEO = timeout
self._socketIn.connect('tcp://%s:%s' % (self._ipAddress,self._portIn))
try:
self._socketIn.setsockopt(zmq.SUBSCRIBE, '') # python2
except TypeError:
self._socketIn.setsockopt_string(zmq.SUBSCRIBE, '') # python3, if this throws an exception... give up...
def recv(self):
msg = self._socketIn.recv()
pdu = pmt.deserialize_str(msg)
cdr = pmt.to_python(pmt.cdr(pdu))
cdr = numpy.getbuffer(cdr)
return cdr
Reusing Existing GNU Radio Types
Edit CMakeLists.txt:
########################################################################
# Find gnuradio build dependencies
########################################################################
find_package(CppUnit)
find_package(Doxygen)
# Search for GNU Radio and its components and versions. Add any
# components required to the list of GR_REQUIRED_COMPONENTS (in all
# caps such as FILTER or FFT) and change the version to the minimum
# API compatible version required.
#set(GR_REQUIRED_COMPONENTS RUNTIME)
set(GR_REQUIRED_COMPONENTS RUNTIME DIGITAL ANALOG FILTER FFT BLOCKS PMT)