Skip to content

Instantly share code, notes, and snippets.

@trondeau
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trondeau/7d5d06ea2f0586f0e9e4 to your computer and use it in GitHub Desktop.
Save trondeau/7d5d06ea2f0586f0e9e4 to your computer and use it in GitHub Desktop.
patch for gr::blocks::deinterleave to handle multiple blocks of data at once
diff --git a/gr-blocks/lib/deinterleave_impl.cc b/gr-blocks/lib/deinterleave_impl.cc
index c9d0e9a..9e18c35 100644
--- a/gr-blocks/lib/deinterleave_impl.cc
+++ b/gr-blocks/lib/deinterleave_impl.cc
@@ -41,13 +41,20 @@ namespace gr {
io_signature::make (1, io_signature::IO_INFINITE, itemsize)),
d_itemsize(itemsize), d_blocksize(blocksize), d_current_output(0)
{
+ d_size_bytes = d_itemsize * d_blocksize;
set_output_multiple(blocksize);
}
+ void
+ deinterleave_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = noutput_items * d_noutputs;
+ }
+
bool
deinterleave_impl::check_topology(int ninputs, int noutputs)
{
- set_relative_rate((double)noutputs);
+ set_relative_rate(1.0/(double)noutputs);
d_noutputs = noutputs;
return true;
}
@@ -61,10 +68,29 @@ namespace gr {
const char *in = (const char*)input_items[0];
char **out = (char**)&output_items[0];
- memcpy(out[d_current_output], in, d_itemsize * d_blocksize);
- consume_each(d_blocksize);
- produce(d_current_output, d_blocksize);
- d_current_output = (d_current_output + 1) % d_noutputs;
+ int count = 0, totalcount = noutput_items*d_noutputs;
+ unsigned int skip = 0;
+ unsigned int acc = 0;
+ while(count < totalcount) {
+ memcpy(out[d_current_output]+skip*d_size_bytes, in, d_size_bytes);
+ in += d_size_bytes;
+ produce(d_current_output, d_blocksize);
+ d_current_output = (d_current_output + 1) % d_noutputs;
+
+ // accumulate times through the loop; increment skip after a
+ // full pass over the output streams.
+ // This is separate than d_current_output since we could be in
+ // the middle of a loop when we exit.
+ acc++;
+ if(acc >= d_noutputs) {
+ skip++;
+ acc = 0;
+ }
+
+ // Keep track of our loop counter
+ count+=d_blocksize;
+ }
+ consume_each(totalcount);
return WORK_CALLED_PRODUCE;
}
diff --git a/gr-blocks/lib/deinterleave_impl.h b/gr-blocks/lib/deinterleave_impl.h
index 247ee3a..71a551a 100644
--- a/gr-blocks/lib/deinterleave_impl.h
+++ b/gr-blocks/lib/deinterleave_impl.h
@@ -35,11 +35,12 @@ namespace gr {
unsigned int d_blocksize;
unsigned int d_current_output;
unsigned int d_noutputs;
-
+ unsigned int d_size_bytes; // block size in bytes
public:
deinterleave_impl(size_t itemsize, unsigned int blocksize);
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
bool check_topology(int ninputs, int noutputs);
int general_work(int noutput_items,
@mbr0wn
Copy link

mbr0wn commented Sep 23, 2014

I'm wondering if this is actually the most optimal solution: Your loop exit condition is

while(count < noutput_items)

yet you increase count in every loop. Isn't noutput_items the number available in every output buffer? I.e. shouldn't you increase count every time skip is incremented?

@trondeau
Copy link
Author

Updated from what mbr0wn suggested.We had to properly set forecast for this to work, too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment