GNU Radio 没有来自其他块的输出与我自己的 OOT 块并行
GNU Radio no output from other blocks parallel with my own OOT block
我想用 C++ 为 GNU Radio 编写具有 1 个输入和 1 个输出的通用块。我按照 gnuradio.org 中的步骤使用 gr_modtool。它可以很好地工作。但是当我将其他块(scope sink2)与相同的源连接时,其中没有输出。
我把流程图连接成:
/-> Scope Sink2
Signal Source -> Throttle -|
\-> my own block -> Scope Sink1
我正在使用 GNU Radio Companion v3.7.6.1-65-g500517ac
我创建了块 'energy_de'。这将创建其他四个文件:
energy_de.h
#ifndef INCLUDED_CPP_ENERGY_DE_H
#define INCLUDED_CPP_ENERGY_DE_H
#include <cpp/api.h>
#include <gnuradio/block.h>
namespace gr {
namespace cpp {
/*!
* \brief <+description of block+>
* \ingroup cpp
*
*/
class CPP_API energy_de : virtual public gr::block
{
public:
typedef boost::shared_ptr<energy_de> sptr;
/*!
* \brief Return a shared_ptr to a new instance of cpp::energy_de.
*
* To avoid accidental use of raw pointers, cpp::energy_de's
* constructor is in a private implementation
* class. cpp::energy_de::make is the public interface for
* creating new instances.
*/
static sptr make(float makenoise);
virtual float noise () const = 0;
virtual void set_noise (float noise) = 0;
};
} // namespace cpp
} // namespace gr
energy_de_impl.h
#ifndef INCLUDED_CPP_ENERGY_DE_IMPL_H
#define INCLUDED_CPP_ENERGY_DE_IMPL_H
#include <cpp/energy_de.h>
namespace gr {
namespace cpp {
class energy_de_impl : public energy_de
{
private:
float d_noise;
public:
energy_de_impl(float noise);
~energy_de_impl();
// Where all the action really happens
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
float noise() const { return d_noise; }
void set_noise(float noise) { d_noise = noise; }
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 cpp
} // namespace gr
energy_de_impl.cc
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "energy_de_impl.h"
namespace gr {
namespace cpp {
energy_de::sptr
energy_de::make(float noise)
{
return gnuradio::get_initial_sptr
(new energy_de_impl(noise));
}
/*
* The private constructor
*/
energy_de_impl::energy_de_impl(float noise)
: gr::block("energy_de",
gr::io_signature::make(1, 1, sizeof(float)),
gr::io_signature::make(1, 1, sizeof(float))),
d_noise(noise)
{
}
/*
* Our virtual destructor.
*/
energy_de_impl::~energy_de_impl()
{
}
void
energy_de_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
ninput_items_required[0] = noutput_items;
}
int
energy_de_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 float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];
for(int i = 0; i < noutput_items; i++){
if (in[i]*in[i] > d_noise){
out[i] = 1.0;
}
else{
out[i] = 0.0;
}
}
return noutput_items;
}
} /* namespace cpp */
} /* namespace gr */
cpp_energy_de.xml
<?xml version="1.0"?>
<block>
<name>energy_de</name>
<key>cpp_energy_de</key>
<category>cpp</category>
<import>import cpp</import>
<make>cpp.energy_de($noise)</make>
<callback>set_niose($noise)</callback>
<param>
<name>noise</name>
<key>noise</key>
<type>float</type>
</param>
<sink>
<name>in</name>
<type>float</type>
</sink>
<source>
<name>out</name>
<type>float</type>
</source>
</block>
为什么我无法从 Scope Sink2 获得输出?我忘记在四个文件中写什么了?这是关于我的块的 input_items 缓冲区的问题吗?
当使用一般 block
而不是 sync_block
时,您的 general_work
必须 调用 consume
,表明有多少你读过的项目,否则你自己的块的输入缓冲区(== throttle 的输出缓冲区)很快就会填满,throttle 无法将新样本放入其中并且你的流程图停止。那时,您的示波器接收器可能根本没有足够的输入来显示任何内容。
我认为对于您的用例,仅使用 sync_block
会容易得多,因此也是执行此操作的正确方法。
我想给你指一个 mail I've written today to the discuss GNU Radio mailing list。它解释了这背后的缓冲区 space 概念。
/->A->Null Sink
File Source -|
\->B->File Sink
[...]
So the mechanism below is: the output buffer of File Source is the
input buffer of A and the input buffer of B. No memory duplication
here.
File Source has a buffer writer with a write pointer, and A and B have
their own read pointers pointing into that buffer.
When File Source produces N items, the write pointer advances by N.
Similarly, when A consumes M items, A's read pointer advances by M.
When calling (general_)work, the input_items buffer(s) is (are) really
just a pointer (start_of_buffer + read pointer). Equivalently, the
output_items buffer(s) is (are) really just pointing to the write
pointer.
File Source is only allowed to produce so many items that the write pointer doesn't advance beyond the minimum read pointer, because in that case, it would overwrite samples that a downstream block hasn't consumed.
我想用 C++ 为 GNU Radio 编写具有 1 个输入和 1 个输出的通用块。我按照 gnuradio.org 中的步骤使用 gr_modtool。它可以很好地工作。但是当我将其他块(scope sink2)与相同的源连接时,其中没有输出。
我把流程图连接成:
/-> Scope Sink2
Signal Source -> Throttle -|
\-> my own block -> Scope Sink1
我正在使用 GNU Radio Companion v3.7.6.1-65-g500517ac
我创建了块 'energy_de'。这将创建其他四个文件: energy_de.h
#ifndef INCLUDED_CPP_ENERGY_DE_H
#define INCLUDED_CPP_ENERGY_DE_H
#include <cpp/api.h>
#include <gnuradio/block.h>
namespace gr {
namespace cpp {
/*!
* \brief <+description of block+>
* \ingroup cpp
*
*/
class CPP_API energy_de : virtual public gr::block
{
public:
typedef boost::shared_ptr<energy_de> sptr;
/*!
* \brief Return a shared_ptr to a new instance of cpp::energy_de.
*
* To avoid accidental use of raw pointers, cpp::energy_de's
* constructor is in a private implementation
* class. cpp::energy_de::make is the public interface for
* creating new instances.
*/
static sptr make(float makenoise);
virtual float noise () const = 0;
virtual void set_noise (float noise) = 0;
};
} // namespace cpp
} // namespace gr
energy_de_impl.h
#ifndef INCLUDED_CPP_ENERGY_DE_IMPL_H
#define INCLUDED_CPP_ENERGY_DE_IMPL_H
#include <cpp/energy_de.h>
namespace gr {
namespace cpp {
class energy_de_impl : public energy_de
{
private:
float d_noise;
public:
energy_de_impl(float noise);
~energy_de_impl();
// Where all the action really happens
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
float noise() const { return d_noise; }
void set_noise(float noise) { d_noise = noise; }
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 cpp
} // namespace gr
energy_de_impl.cc
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "energy_de_impl.h"
namespace gr {
namespace cpp {
energy_de::sptr
energy_de::make(float noise)
{
return gnuradio::get_initial_sptr
(new energy_de_impl(noise));
}
/*
* The private constructor
*/
energy_de_impl::energy_de_impl(float noise)
: gr::block("energy_de",
gr::io_signature::make(1, 1, sizeof(float)),
gr::io_signature::make(1, 1, sizeof(float))),
d_noise(noise)
{
}
/*
* Our virtual destructor.
*/
energy_de_impl::~energy_de_impl()
{
}
void
energy_de_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
ninput_items_required[0] = noutput_items;
}
int
energy_de_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 float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];
for(int i = 0; i < noutput_items; i++){
if (in[i]*in[i] > d_noise){
out[i] = 1.0;
}
else{
out[i] = 0.0;
}
}
return noutput_items;
}
} /* namespace cpp */
} /* namespace gr */
cpp_energy_de.xml
<?xml version="1.0"?>
<block>
<name>energy_de</name>
<key>cpp_energy_de</key>
<category>cpp</category>
<import>import cpp</import>
<make>cpp.energy_de($noise)</make>
<callback>set_niose($noise)</callback>
<param>
<name>noise</name>
<key>noise</key>
<type>float</type>
</param>
<sink>
<name>in</name>
<type>float</type>
</sink>
<source>
<name>out</name>
<type>float</type>
</source>
</block>
为什么我无法从 Scope Sink2 获得输出?我忘记在四个文件中写什么了?这是关于我的块的 input_items 缓冲区的问题吗?
当使用一般 block
而不是 sync_block
时,您的 general_work
必须 调用 consume
,表明有多少你读过的项目,否则你自己的块的输入缓冲区(== throttle 的输出缓冲区)很快就会填满,throttle 无法将新样本放入其中并且你的流程图停止。那时,您的示波器接收器可能根本没有足够的输入来显示任何内容。
我认为对于您的用例,仅使用 sync_block
会容易得多,因此也是执行此操作的正确方法。
我想给你指一个 mail I've written today to the discuss GNU Radio mailing list。它解释了这背后的缓冲区 space 概念。
/->A->Null Sink File Source -| \->B->File Sink
[...]
So the mechanism below is: the output buffer of File Source is the input buffer of A and the input buffer of B. No memory duplication here.
File Source has a buffer writer with a write pointer, and A and B have their own read pointers pointing into that buffer.
When File Source produces N items, the write pointer advances by N.
Similarly, when A consumes M items, A's read pointer advances by M.
When calling (general_)work, the input_items buffer(s) is (are) really just a pointer (start_of_buffer + read pointer). Equivalently, the output_items buffer(s) is (are) really just pointing to the write pointer.
File Source is only allowed to produce so many items that the write pointer doesn't advance beyond the minimum read pointer, because in that case, it would overwrite samples that a downstream block hasn't consumed.