Using general_work when output rate is not fixed

All,

I have made a simple custom block (derived from gr_block class) whose
general_work() function is given below:

int howto_my_custom_blk::general_work (int noutput_items, gr_vector_int
&ninput_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items){
const gr_complex *in = (const gr_complex *) input_items[0];
const short *trigger = (const short *) input_items[1];
gr_complex *out = (gr_complex *) output_items[0];

int ninput_items_used_in_this_work_call;
ninput_items_used_in_this_work_call = 0;

for (int i = 0; i < noutput_items; i++){
if (trigger[i] > 0) {
out[i] = in[i];
ninput_items_used_in_this_work_call++;
if (!tx_sob_sent) { this->make_sob_tag(this->nitems_written(0)

  • i); tx_sob_sent = true; tx_eob_sent = false;}

    }
    else {
    if (!tx_eob_sent) { this->make_eob_tag(this->nitems_written(0) +
    i-1); tx_eob_sent = true; tx_sob_sent = false; }
    }
    }
    consume_each (ninput_items[0]);

    return ninput_items_used_in_this_work_call;
    }

Some comments about the block ports:
In above custom block code,

  • in is an input which comes from uhd_usrp_source and consists of set of
    packets sent by some packet transmitter.
  • trigger is an input which goes high (>0) every time a packet is
    detected and remains high thereafter for the duration of packet. It is
    essentially Tom’s energy detection mechanism borrowed from
    uhd_burst_detector.py.
  • out is the block output which goes to uhd_usrp_sink.
    In short, my custom block receives a set of packets and forwards it to
    the tx side of the usrp.

Now, I have some questions which are as follows:

  • When trigger goes high, the input samples at in (which correspond to
    the received packet) should be copied to the output and then sent to the
    uhd_usrp sink. But this is not the case, as I see using the external
    oscilloscope (and by recording the output out of the block into a file)
    that instead the noise samples are copied to output. Why it is so?
  • As can be seen, general_work() returns
    ninput_items_used_in_this_work_call every time it is called by
    scheduler. Since trigger remains low most of the time, it means
    general_work() will produce no output samples most of the times it is
    called. But the output port out is connected to uhd_usrp_source which
    will produce underruns every time my custom block does not produce an
    output. I have put sob and eob tags to eliminate this problem but did
    not succeed. Any ideas, what might be wrong?
  • Since my custom block is not a fixed ratio block, how should I
    override the forecast function, or, is it optional and meant for
    efficiency purposes?

Thanks,
Mahboob

On Sun, Sep 9, 2012 at 6:39 PM, Rahman, Muhammad Mahboob Ur
[email protected] wrote:

gr_complex *out = (gr_complex *) output_items[0];

}
else {
    if (!tx_eob_sent) { this->make_eob_tag(this->nitems_written(0) +

i-1); tx_eob_sent = true; tx_sob_sent = false; }
}
}
consume_each (ninput_items[0]);

return ninput_items_used_in_this_work_call;
}

Hi Mahboob,

I would consume_each(noutput_items) since ninput_items[0] >=
noutput_items (I’m guessing you are using the standard forecast
function), but you are only looking over noutput_items in your for
loop. So you might have more inputs available that you are looking at
and by consuming all of the inputs, you might be dropping data. So
look at that and see if it solves your main problem.

The other thing is that the way we handled it in the burst detector
was that we send a tag once when the burst signal goes high and then
another when it goes low. It looks like you are sending a tag every
time trigger > 0, which could mean you will be sending a lot of tags
through the system, which can be expensive. This is an optimization
for the scheduler, but a pretty big one since moving
hundreds/thousands of tags a second through the scheduler will
significantly impact the performance.

Hope this helps,
Tom

Hi Tom & All,

I am now doing consume_each(noutput_items) but my problem is not solved
yet. I have also made sure that my code effectively sends one sob tag
and one eob tag per burst of samples.

Questions about new experiment:
Now, I have created yet another simple experiment whose flow-graph is as
follows:

uhd usrp source --> my custom block --> uhd usrp sink
|
–> file sink

The relevant code of my custom block is below:
int
howto_send_discont::general_work (…) {

int ninput_items_used_in_this_work_call;
ninput_items_used_in_this_work_call = 0;

for (int i = 0; i < noutput_items; i++){

samp_count++;
if (samp_count == 1) { out[i] = gr_complex(0.7,0); 

this->make_sob_tag(this->nitems_written(0)+i);}
else if (samp_count == 2) { out[i] = gr_complex(0.7,0);
this->make_eob_tag(this->nitems_written(0)+i);}
else if (samp_count == 25000) {
samp_count = 0; send_tx_pkt = true; pkt_no++; }
if (send_tx_pkt) {
pkt_samp_no++;
ninput_items_used_in_this_work_call++;
/if (total_samps_outputted_so_far == 7761) {
pkt_samp_no = 1; samp_count = 1;
total_samps_outputted_so_far = 10000; pkt_no = 0; }
else if (total_samps_outputted_so_far < 7761){
total_samps_outputted_so_far++; }
/
out[i] = gmsk_pkt_samples_2[pkt_samp_no-1];
if (pkt_samp_no == 1) {
this->make_sob_tag(this->nitems_written(0)+i);
}
else if (pkt_samp_no == 1536) {
this->make_eob_tag(this->nitems_written(0)+i);
pkt_samp_no = 0;
send_tx_pkt = false;
}
}

}

consume_each (noutput_items);

// Tell runtime system how many output items we produced.
return ninput_items_used_in_this_work_call;
}

You can see from the above code that my custom block maintains an
internal counter samp_count which causes the custom block to output N
samples whenever internal counter’s count equals M (N=1536, M=25000 in
my case). I use the same counter to initially send a burst of 2 samples
to uhd usrp sink after attaching sob and eob tags so as to avoid
underflow problem at the transmit side. But my problems are persistent
which are:

  • I see many zero-valued samples among the first 7761 output samples of
    my custom block, even when the samples my custom block should output are
    either constant valued samples or pre-recorded GMSK samples (depending
    upon which line is uncommented in my above code). Why it is so?

  • Even though I have avoided the above mentioned problem by noticing
    that in my case, after first 7761 samples, all the subsequent samples
    are correct. So, I use another counter to start all over again (to reset
    the functionality of my block) once my custom block has sent 7761
    samples to uhd usrp sink. Now, the other issue is, when I send
    pre-recorded GMSK samples to the uhd usrp sink, I still see lot of
    underruns occuring indefinitely at tx side. Why are the sob and eob tags
    being ineffective? Moreover, when those GMSK packets are received at
    another node, the packet decode rate is too low over there (I guess not
    all of the samples corresponding to many GMSK packets are being
    transmitted from node1, fix me).

Thanks in anticipation for your help,
Mahboob