Sunday, September 3, 2017

[Discuss-gnuradio] My OOT Module sometimes working and sometimes giving Error

/* -*- c++ -*- */
/*
* Copyright 2017 <+YOU OR YOUR COMPANY+>.
*
* This 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.
*
* This software 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 this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gnuradio/io_signature.h>
#include "my_demux_impl.h"

namespace gr {
namespace my_module_demux {


enum demux_states_t {
STATE_FIND_TRIGGER, // "Idle" state (waiting for burst)
STATE_HEADER // Copy data
};

enum out_port_indexes_t {
PORT_HEADER = 0,
PORT_INPUTDATA = 0,
PORT_TRIGGER = 1
};

my_demux::sptr
my_demux::make(
int header_len,
int items_per_symbol,
const std::string &trigger_tag_key,
unsigned int itemsize,
const float samp_rate
){
return gnuradio::get_initial_sptr(
new my_demux_impl(
header_len,
items_per_symbol,
trigger_tag_key,
itemsize,
samp_rate
)
);
}

/*
* The private constructor
*/
my_demux_impl::my_demux_impl(
int header_len,
int items_per_symbol,
const std::string &trigger_tag_key,
unsigned int itemsize,
const float samp_rate
) : gr::block("my_demux",
gr::io_signature::make2(1, 2, itemsize, sizeof(char)),
gr::io_signature::make(1, 1, itemsize)),
d_header_len(header_len),
d_items_per_symbol(items_per_symbol),
d_trigger_tag_key(pmt::string_to_symbol(trigger_tag_key)),
d_itemsize(itemsize),
d_uses_trigger_tag(!trigger_tag_key.empty()),
d_state(STATE_FIND_TRIGGER),
d_sampling_time(1.0/samp_rate)
{
if (d_header_len < 1) {
throw std::invalid_argument("Header length must be at least 1 symbol.");
}
if (d_items_per_symbol < 1 || d_itemsize < 1) {
throw std::invalid_argument("Items and symbol sizes must be at least 1.");
}
set_relative_rate(1.0);
set_output_multiple(d_items_per_symbol);
set_tag_propagation_policy(TPP_DONT);
}

/*
* Our virtual destructor.
*/
my_demux_impl::~my_demux_impl()
{
}

// forecast() depends on state:
// - When waiting for a Header, we require at least the header length
// - Otherwise, pretend this is a sync block with a decimation/interpolation
// depending on symbol size and if we output symbols or items

void
my_demux_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
int n_items_reqd = 0;
if (d_state == STATE_HEADER){
n_items_reqd = d_header_len * d_items_per_symbol;
}else{
n_items_reqd = noutput_items;
}
for (unsigned int i = 0; i < ninput_items_required.size(); i++){
ninput_items_required[i] = n_items_reqd;
}
}

int
my_demux_impl::general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[PORT_INPUTDATA];
unsigned char *out_header = (unsigned char *) output_items[PORT_HEADER];

const int n_input_items = (ninput_items.size() == 2) ?
std::min(ninput_items[0], ninput_items[1]) :
ninput_items[0];

// Items read going into general_work()
const uint64_t n_items_read_base = nitems_read(PORT_INPUTDATA);
// Items read during this call to general_work()
int n_items_read = 0;

#define CONSUME_ITEMS(items_to_consume) \
consume_each(items_to_consume); \
n_items_read += (items_to_consume); \
in += (items_to_consume) * d_itemsize;

switch (d_state){
case STATE_FIND_TRIGGER:{
// Assumptions going into this state:
// - No other state was active for this call to general_work()
// - i.e. n_items_read == 0
// Start looking for a trigger after any header padding.
// The trigger offset is relative to 'in'.
// => The absolute trigger offset is on n_items_read_base + n_items_read + trigger_offset
const int max_rel_offset = n_input_items - n_items_read;
const int trigger_offset = find_trigger_signal(
max_rel_offset,
n_items_read_base + n_items_read,
(input_items.size() == 2) ?
((const unsigned char *) input_items[PORT_TRIGGER]) + n_items_read : NULL
);
if (trigger_offset < max_rel_offset){
d_state = STATE_HEADER;
}
const int items_to_consume = trigger_offset;
CONSUME_ITEMS(items_to_consume);
break;
} /* case STATE_FIND_TRIGGER */

case STATE_HEADER:{
// Assumptions going into this state:
// - The first items on `in' are the Data samples
// - So we can just copy from the beginning of `in'
// - The trigger is on item index `d_header_padding * d_items_per_symbol'
// Actions:
// - Copy the entire header to the Output port

if (check_buffers_ready(
d_header_len,
noutput_items,
d_header_len * d_items_per_symbol,
ninput_items,
n_items_read)) {
copy_n_symbols(
in,
out_header,
PORT_HEADER,
n_items_read_base + n_items_read,
d_header_len // Number of symbols to copy
);
}
const int items_to_consume = d_header_len * d_items_per_symbol;
CONSUME_ITEMS(items_to_consume);
d_state = STATE_FIND_TRIGGER;
break;
} /* case STATE_HEADER */

default:
throw std::runtime_error("invalid state");
} /* switch */
return WORK_CALLED_PRODUCE;
} /* general_work */

int
my_demux_impl::find_trigger_signal(
int max_rel_offset,
uint64_t base_offset,
const unsigned char *in_trigger
) {
int rel_offset = max_rel_offset;
if (in_trigger) {
for (int i = 0; i < max_rel_offset; i++) {
if (in_trigger[i]) {
rel_offset = i;
break;
}
}
}
return rel_offset;
} /* find_trigger_signal() */

bool
my_demux_impl::check_buffers_ready(
int output_symbols_reqd,
int noutput_items,
int input_items_reqd,
gr_vector_int &ninput_items,
int n_items_read
) {
// Check there's enough space on the output buffer
if (noutput_items < (output_symbols_reqd * d_items_per_symbol)) {
return false;
}

// Check there's enough items on the input
if (input_items_reqd > (ninput_items[0]-n_items_read)
|| (ninput_items.size() == 2 && (input_items_reqd > (ninput_items[1]-n_items_read)))) {
return false;
}
// All good
return true;
} /* check_buffers_ready */

void
my_demux_impl::copy_n_symbols(
const unsigned char *in,
unsigned char *out,
int port,
const uint64_t n_items_read_base,
int n_symbols
) {
// Copy samples
memcpy(
(void *) out,
(void *) in,
(n_symbols * d_items_per_symbol) * d_itemsize
);
// Advance write pointers
// Items to produce might actually be symbols
const int items_to_produce = n_symbols * d_items_per_symbol;
produce(port, items_to_produce);
} /* copy_n_symbols() */

} /* namespace my_module_demux */
} /* namespace gr */
/* -*- c++ -*- */
/*
* Copyright 2017 <+YOU OR YOUR COMPANY+>.
*
* This 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.
*
* This software 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 this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/

#ifndef INCLUDED_MY_MODULE_DEMUX_MY_DEMUX_IMPL_H
#define INCLUDED_MY_MODULE_DEMUX_MY_DEMUX_IMPL_H

#include <my_module_demux/my_demux.h>

namespace gr {
namespace my_module_demux {

class my_demux_impl : public my_demux
{
private:
int d_header_len; //!< Number of bytes per header
int d_items_per_symbol; //!< Bytes per symbol
pmt::pmt_t d_trigger_tag_key; //!< Key of trigger tag (if used)
size_t d_itemsize; //!< Bytes per item
bool d_uses_trigger_tag; //!< If a trigger tag is used
int d_state; //!< Current read state
double d_sampling_time; //!< Inverse sampling rate

int find_trigger_signal(
int max_rel_offset,
uint64_t base_offset,
const unsigned char *in_trigger
);

bool
check_buffers_ready(
int output_symbols_reqd,
int noutput_items,
int input_items_reqd,
gr_vector_int &ninput_items,
int n_items_read
);

void
copy_n_symbols(
const unsigned char *in,
unsigned char *out,
int port,
const uint64_t n_items_read_base,
int n_symbols
);

public:
my_demux_impl(int header_len, int items_per_symbol, const std::string &trigger_tag_key, unsigned int itemsize, const float samp_rate);
~my_demux_impl();

// Where all the action really happens
void forecast (int noutput_items, gr_vector_int &ninput_items_required);

int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};

} // namespace my_module_demux
} // namespace gr

#endif /* INCLUDED_MY_MODULE_DEMUX_MY_DEMUX_IMPL_H */

I am trying to make a block which copies (samples_per_symbol * no. of symbols ) samples from the input 0 stream whenever it receives a trigger (i.e. a 1) in input 1 stream.

My block is giving expected output when it runs but when it does not work in gnuradio companion it gives this error. 

%---------------------------

Traceback (most recent call last):
  File "/home/raghav/Documents/Project/gnuradio/my_demux_test/top_block.py", line 123, in <module>
    main()
  File "/home/raghav/Documents/Project/gnuradio/my_demux_test/top_block.py", line 111, in main
    tb = top_block_cls()
  File "/home/raghav/Documents/Project/gnuradio/my_demux_test/top_block.py", line 88, in __init__
    self.connect((self.my_module_demux_my_demux_1, 0), (self.blocks_throttle_0, 0))
  File "/usr/local/lib/python2.7/dist-packages/gnuradio/gr/hier_block2.py", line 47, in wrapped
    func(self, src, src_port, dst, dst_port)
  File "/usr/local/lib/python2.7/dist-packages/gnuradio/gr/hier_block2.py", line 110, in connect
    self.primitive_connect(*args)
  File "/usr/local/lib/python2.7/dist-packages/gnuradio/gr/runtime_swig.py", line 5334, in primitive_connect
    return _runtime_swig.top_block_sptr_primitive_connect(self, *args)
ValueError: port number 0 exceeds max of (none)

>>> Done (return code -11)

%-------------------------------------

I am attaching both the flowgraph that I use for testing and the code I a have written for creating OOT module.

The code is almost similar to the code of header_payload_demux block.

Please look into this as soon as possible.


Regards,
Raghav Gupta
MTech. Research Assistant, IIT Bombay

No comments:

Post a Comment