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
/* -*- 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 */

Attachment: untitled.grc
Description: application/gnuradio-grc

_______________________________________________
Discuss-gnuradio mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio

Reply via email to