//
// Copyright 2012 Josh Blum
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
#include "element_impl.hpp"
#include "pmx_helper.hpp"
#include
#include
gr_block::gr_block(void)
{
//NOP
}
gr_block::gr_block(
const std::string &name,
gr_io_signature_sptr input_signature,
gr_io_signature_sptr output_signature
):
gnuradio::Block(name)
{
this->set_fixed_rate(false);
this->set_input_signature(input_signature);
this->set_output_signature(output_signature);
}
int gr_block::work(
const InputItems &input_items,
const OutputItems &output_items
){
return this->general_work(
(*this)->block->work_noutput_items,
(*this)->block->work_ninput_items,
(*this)->block->work_input_items,
(*this)->block->work_output_items
);
}
void gr_block::forecast(int noutput_items, std::vector &ninputs_req)
{
for (size_t i = 0; i < ninputs_req.size(); i++)
{
ninputs_req[i] = fixed_rate_noutput_to_ninput(noutput_items);
}
}
int gr_block::general_work(
int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items
){
throw std::runtime_error("gr_block subclasses must overload general_work!");
}
void gr_block::set_alignment(const size_t)
{
//TODO
//probably dont need this since buffers always start aligned
//and therefore alignment is always re-acheived
}
bool gr_block::is_unaligned(void)
{
//TODO
//probably dont need this since volk dispatcher checks alignment
//32 byte aligned is good enough for you
return ((*this)->block->work_io_ptr_mask & ptrdiff_t(GRAS_MAX_ALIGNMENT-1)) != 0;
}
size_t gr_block::fixed_rate_noutput_to_ninput(const size_t noutput_items)
{
if (this->fixed_rate())
{
return size_t(0.5 + (noutput_items/this->relative_rate())) + this->history() - 1;
}
else
{
return noutput_items + this->history() - 1;
}
}
size_t gr_block::interpolation(void) const
{
return size_t(1.0*this->relative_rate());
}
void gr_block::set_interpolation(const size_t interp)
{
this->set_relative_rate(1.0*interp);
this->set_output_multiple(interp);
}
size_t gr_block::decimation(void) const
{
return size_t(1.0/this->relative_rate());
}
void gr_block::set_decimation(const size_t decim)
{
this->set_relative_rate(1.0/decim);
}
unsigned gr_block::history(void) const
{
//implement off-by-one history compat
return this->input_config().lookahead_items+1;
}
void gr_block::set_history(unsigned history)
{
gnuradio::InputPortConfig config = this->input_config();
//implement off-by-one history compat
if (history == 0) history++;
config.lookahead_items = history-1;
this->set_input_config(config);
}
int gr_block::max_noutput_items(void) const
{
return this->output_config().maximum_items;
}
void gr_block::set_max_noutput_items(int max_items)
{
gnuradio::OutputPortConfig config = this->output_config();
config.maximum_items = max_items;
this->set_output_config(config);
}
void gr_block::unset_max_noutput_items(void)
{
this->set_max_noutput_items(0);
}
bool gr_block::is_set_max_noutput_items(void) const
{
return this->max_noutput_items() != 0;
}
//TODO Tag2gr_tag and gr_tag2Tag need PMC to/from PMT logic
//currently PMC holds the pmt_t, this is temporary
static gr_tag_t Tag2gr_tag(const gnuradio::Tag &tag)
{
gr_tag_t t;
t.offset = tag.offset;
t.key = tag.key? tag.key.as() : pmt::pmt_t();
t.value = tag.value? tag.value.as() : pmt::pmt_t();
t.srcid = tag.srcid? tag.srcid.as() : pmt::pmt_t();
return t;
}
static gnuradio::Tag gr_tag2Tag(const gr_tag_t &tag)
{
return gnuradio::Tag(tag.offset, PMC::make(tag.key), PMC::make(tag.value), PMC::make(tag.srcid));
}
void gr_block::add_item_tag(
const size_t which_output, const gr_tag_t &tag
){
this->post_output_tag(which_output, gr_tag2Tag(tag));
}
void gr_block::add_item_tag(
const size_t which_output,
uint64_t abs_offset,
const pmt::pmt_t &key,
const pmt::pmt_t &value,
const pmt::pmt_t &srcid
){
gr_tag_t t;
t.offset = abs_offset;
t.key = key;
t.value = value;
t.srcid = srcid;
this->add_item_tag(which_output, t);
}
void gr_block::get_tags_in_range(
std::vector &tags,
const size_t which_input,
uint64_t abs_start,
uint64_t abs_end,
const pmt::pmt_t &key
){
tags.clear();
BOOST_FOREACH(const gnuradio::Tag &tag, this->get_input_tags(which_input))
{
if (tag.offset >= abs_start and tag.offset <= abs_end)
{
gr_tag_t t = Tag2gr_tag(tag);
if (key or pmt::pmt_equal(t.key, key)) tags.push_back(t);
}
}
}