Gnuradio block behaves strange.....please have a look at this

Hi friends,

I wrote a gnuradio block that has 2 input streams.

  1. The first stream is the stream of PN sequence data coming out of an
    gr.xor_bb block. (It is a gold sequence generated by XOR two M-seq
    generated
    using gr.glfsr_source_b).
  2. The second stream is the data read from a file. I use a test data
    "0xAA "
    stored in a file and read it using
    gr.file_source(gr.sizeof_char,“datafile”,True).

The output is written to a file. The output written to the file always
has
some data missing. I tested the spreading block by printing its output
to
“stdout” and found that the output is alright, but when I write it to
the
file I always see some data missing. Any ideas why this might be
happening ?

Below is the code for the block that spreads the data. I spread each bit
of
every byte read to the lenth of PN sequence. e.g. If PN sequence is 7
bit
long, the output of the block will be 7*8 bits for each byte read from
the
file. The PN sequence bit is the LSB of every byte that output out of
the
XOR block.

I suspect something is wrong with the way I call the “consume” function.

Any kind of help will be greatly appreciated.

Thanks
Ali.

The code.

// dsss_spreading_blk_b.h

/* -- c++ -- /
/

  • Copyright 2004 Free Software Foundation, Inc.
  • This file is part of GNU Radio
  • GNU Radio 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.
  • GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
  • the Free Software Foundation, Inc., 51 Franklin Street,
  • Boston, MA 02110-1301, USA.
    */

#ifndef INCLUDED_DSSS_SPREADING_BLK_B_H
#define INCLUDED_DSSS_SPREADING_BLK_B_H

#include <gr_block.h>

class dsss_spreading_blk_b;
typedef boost::shared_ptr<dsss_spreading_blk_b>
dsss_spreading_blk_b_sptr;

dsss_spreading_blk_b_sptr dsss_make_spreading_blk_b (int degree_PN);

class dsss_spreading_blk_b : public gr_block
{
int d_length_PN;
friend dsss_spreading_blk_b_sptr dsss_make_spreading_blk_b(int
degree_PN);
dsss_spreading_blk_b(int degree_PN);

public:
    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);
};

#endif /* INCLUDED_DSSS_SPREADING_BLK_B_H /
//
**********************************************************************************

// dsss_spreading_blk_b.cc

/* -- c++ -- /
/

  • Copyright 2004 Free Software Foundation, Inc.
  • This file is part of GNU Radio
  • GNU Radio 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.
  • GNU Radio 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 GNU Radio; 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 <dsss_spreading_blk_b.h>
#include <gr_io_signature.h>
#include <assert.h>
#include
#include
dsss_spreading_blk_b_sptr
dsss_make_spreading_blk_b (int degree_PN)
{
return dsss_spreading_blk_b_sptr (new dsss_spreading_blk_b
(degree_PN));
}

/*
Input_stream_2 = data_source to be spread. The input data size is 1
byte.(1 item is needed to produce 1 output item)
Input_stream_1 = PN_sequence_generator. The input data size is 1
byte.(length_PN items are needed to produce 1 output item)
*/

dsss_spreading_blk_b::dsss_spreading_blk_b(int
degree_PN):gr_block(“spreading_blk”,
gr_make_io_signature(2,2,sizeof(unsigned char)),
gr_make_io_signature(1,1,sizeof(unsigned char))),
d_length_PN((int)(pow(2,degree_PN)-1))
{
set_output_multiple(8*d_length_PN); // noutput_items == multiple of
length of PN sequence
}

void
dsss_spreading_blk_b::forecast(int noutput_items,gr_vector_int
&ninput_items_required){
assert(noutput_items % d_length_PN==0);

//unsigned int ninputs = ninput_items_required.size();
int items_on_first_input_stream = noutput_items; // the first_stream 

is
the PN sequence stream
int items_on_data_input_stream = noutput_items/(8*d_length_PN);
ninput_items_required[0]=items_on_first_input_stream;
ninput_items_required[1]=items_on_data_input_stream;
}

int
dsss_spreading_blk_b::general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
//std::cout << d_length_PN << std::endl;
const unsigned char *in_1 = (const unsigned char *)input_items[0];//
PN
const unsigned char *in_2 = (const unsigned char *)input_items[1];//
data
unsigned char *out = (unsigned char *)output_items[0];
int pn_input_cnt=0;
int items_on_1 = ninput_items[0];
int items_on_2 = ninput_items[1];
int i=0;
int data_cnt=0;
int cc=0;
for(i=0;(i<noutput_items)&&(data_cnt<items_on_2);i++){
data_cnt=data_cnt+1;
//pn_input_cnt=0;
unsigned char temp = in_2[data_cnt-1];
//std::cout << “int_2=” << (int)temp << std::endl;
//std::cout << " in \t" << " out" << std::endl;
for(int j=0;j<8;j++){
pn_input_cnt=0;
if((temp>>j)&0x01){
while(pn_input_cnt<d_length_PN){
//std::cout << " “<< (int)in_1[i] << “\t”;
out[i]=in_1[i];
// std::cout << " \t”<< (int)out[i] << std::endl;
i=i+1;
pn_input_cnt=pn_input_cnt+1;

            }
        }else{
            while(pn_input_cnt<d_length_PN){
                //std::cout << " "<< (int)in_1[i] << "\t";
                out[i]=in_1[i] ^ 0x01;
            //    std::cout << " \t"<< (int)out[i] << std::endl;
                i=i+1;
                pn_input_cnt=pn_input_cnt+1;

            }
        }
    }
    //cc++;
    //if(cc==1)
        //exit(0);
}
consume(0,i);
consume(1,data_cnt);

}

//***************************************************************

//spread.i
/* -- c++ -- /
/

  • Copyright 2007 Free Software Foundation, Inc.
  • This file is part of GNU Radio
  • GNU Radio 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.
  • GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
  • the Free Software Foundation, Inc., 51 Franklin Street,
  • Boston, MA 02110-1301, USA.
    */

%feature(“autodoc”, “1”); // generate python docstrings

%include “exception.i”
%import “gnuradio.i”
// the common stuff
%{
#include “gnuradio_swig_bug_workaround.h” // mandatory bug fix
#include “dsss_spreading_blk_b.h”
#include
%}

GR_SWIG_BLOCK_MAGIC(dsss,spreading_blk_b);

dsss_spreading_blk_b_sptr
dsss_make_spreading_blk_b(int degree_PN)
throw (std::runtime_error);

class dsss_spreading_blk_b:public gr_block
{
protected:
dsss_spreading_blk_b(int degree_PN);
};

On Tue, Sep 30, 2008 at 11:19:54PM -0500, Murtuza wrote:

The output is written to a file. The output written to the file always has

I suspect something is wrong with the way I call the “consume” function.
Any kind of help will be greatly appreciated.

First off, I think this would be easier to understand (and get right)
if both inputs are defined to look at only the LSB. You can use the
gr.packed_to_unpacked block to unpack your data bytes.

Assuming you make this change, then

The PN code is coming in on 0, and it requires 1 input for every
output.
The data is coming in on 1, and it requires 1 input for every
d_length_PN outputs.

Do

set_output_multiple(d_length_PN)

in your constructor

void
dsss_spreading_blk_b::forecast(int noutput_items,
gr_vector_int &ninput_items_required)
{
assert(noutput_items % d_length_PN == 0);
ninput_items_required[0] = noutput_items;
ninput_items_required[1] = noutput_items / d_length_PN;
}

int
dsss_spreading_blk_b::general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star
&input_items,
gr_vector_void_star &output_items)
{
assert(noutput_items % d_length_PN == 0);

const unsigned char *pn = (const unsigned char *)input_items[0]; //
PN
const unsigned char *data = (const unsigned char *)input_items[1]; //
data
unsigned char *out = (unsigned char *)output_items[0];

for(int pi=0, di=0; pi < noutput_items; pi += d_length_PN, di++){
int current_data = pn[di]
for (int j=0; j < d_length_PN; j++){
out[pi + j] = f(current_data, pn[pi])
}
}

consume(0, noutput_items);
consume(1, noutput_items / d_length_PN)
}

On Wed, Oct 01, 2008 at 01:30:59PM -0700, Eric B. wrote:

unsigned char *out = (unsigned char *)output_items[0];

for(int pi=0, di=0; pi < noutput_items; pi += d_length_PN, di++){
int current_data = pn[di]
for (int j=0; j < d_length_PN; j++){
out[pi + j] = f(current_data, pn[pi])

Sorry, should be:

  out[pi + j] = f(current_data, pn[pi + j])

Hi Eric

I did exactly as you told me to do but still I face the same problem. I
use
gr.packed_to_unpacked_bb(1,gr.GR_LSB_FIRST) to send one bit each time
but I
still find some data missing in the destination file. When I print the
output_items to stdout I find no error and the displayed output is
coherent
with the expected output. The problem arises only when I try to write
this
out to a file. I write it to the file in order to test it.

What could be wrong with this code. This is what I do in python.
spread is the gnruadio block that does spreading according to my C++
block.
The input file “/home/murtuza/f” contains only 1 byte which is 0xAA. I
repeatedly read this using “True” in the gr.file_source.

t.connect(b,(s,1))
t.connect(c,(x,0))
t.connect(d,(x,1))
t.connect(x,(s,0))
t.connect(s,ds)
t.start()
t.stop()

What do you think can cause this confusing problem ?

Thanks
Ali

On Sun, Oct 05, 2008 at 04:23:10AM -0500, Murtuza wrote:

Hi Eric

I did exactly as you told me to do but still I face the same problem. I use
gr.packed_to_unpacked_bb(1,gr.GR_LSB_FIRST) to send one bit each time but I
still find some data missing in the destination file.

What, where, and how much data is missing? Is the data incorrect, or
are there gaps, or zeros, or what? You not giving us much to work
with…

Eric

Hi Eric ,

This is the detail.

File source : I have a binary file with only one byte in it. The byte
value
is 0x5B in hex.
PN Sequence : By using
c = gr.glfsr_source_b(3,True,0x05,0x01)
d = gr.glfsr_source_b(3,True,0x06,0x01)
as the m-sequence generators and XORing them together I get a gold-code
sequence of [ 0 1 0 1 0 0 0 ],which when written in HEX should appear as
[00 01 00 01 00 00 00 ] as the sequence of inputs on the input_stream[0]
of
the spread.spreading_blk_b.

As I am reading the data repeatedly from file_source and unpacking it
bit-by-bit using gr.packed_to_unpacked_bb(1,gr.GR_LSB_FIRST) the input
on
input_stream[1] is sequence of either 0x01 or 0x00. In my case one full
sequence of a byte should look like this in HEX at the input_Stream[1]
–>
[01 01 00 01 01 00 01 00] which is 0x5B with the first entry
representing
the LSB of 0x5B .

For each input on input_stream[1] I must get 7 items on output_stream
which
is the gold-code sequence. If I have 0x01 on input_stream[1] I must get
[00
01 00 01 00 00 00 ] and if I have 0x00 on input_stream[1] I must get [01
00
01 00 01 01 01] which is the complement of the PN-sequence.

I check the output_stream on stdout and the values for out[i] each time
is
exactly as it has to be. But the data written to the file is not right.
This
is the data in the output file. The gr.file_sink block takes output from
the
spread.spreading_blk_b block as the input. This is the data I got in the
output file in HEX (arranged in blocks of length of PN-sequence = 2^3 -
1 =
7)

00 00 01 00 00 01 00 01 00 00 01 00 00 01
00 01 00 00 01 01 01 00 01 00 00 00 00 00
00 00 00 00 00 00 01 01 01 01 00 01 00 00
00 01 01 01 00 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 00 00 00 00 00 01 01 00
01 00 00 00 00 01 00 01 00 01 01 00 00 00
00 00 01 01 01 01 00 01 00 00 01 00 01 00
00 00 00 00 01 00 01 01 00 00 00 00 01 01
01 01 00 00 00 00 00 01 01 00 01 00 01 00
00 01 . . . . . . .

Clearly, this data is not right as I must either get a complete
PN-sequence
or the complement of it. The data observed above doesn’t show [00 01 00
01
00 00 00 ] (output when input is 0x01)or [ 01 00 01 00 01 01 01](output
when
input is 0x00). The correct data should look as shown below for 1-byte
of
input i.e. 8 items on input_stream[1].

00 01 00 01 00 00 00 00 01 00 01 00 00 00
01 00 01 00 01 01 01 00 01 00 01 00 00 00
00 01 00 01 00 00 00 01 00 01 00 01 01 01
00 01 00 01 00 00 00 01 00 01 00 01 01 01

I hope this information is good enough for you to help me. Do you want
me to
send my files as a “.tar.gz” compressed file ?

This is what I do in Python(mentioning it again)

t.connect(b,(s,1))
t.connect(c,(x,0))
t.connect(d,(x,1))
t.connect(x,(s,0))
t.connect(s,ds)
t.start()

Thanks once again,
Ali

This is the corrected C++ source code.

/* -- c++ -- /
/

  • Copyright 2004 Free Software Foundation, Inc.
  • This file is part of GNU Radio
  • GNU Radio 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.
  • GNU Radio 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 GNU Radio; 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 <dsss_spreading_blk_b.h>
#include <gr_io_signature.h>
#include <assert.h>
#include
#include
dsss_spreading_blk_b_sptr
dsss_make_spreading_blk_b (int degree_PN)
{
return dsss_spreading_blk_b_sptr (new dsss_spreading_blk_b
(degree_PN));
}

/*
Input_stream_2 = data_source to be spread.
Input_stream_1 = PN_sequence
*/

dsss_spreading_blk_b::dsss_spreading_blk_b(int
degree_PN):gr_block(“spreading_blk”,
gr_make_io_signature(2,2,sizeof(unsigned char)),
gr_make_io_signature(1,1,sizeof(unsigned char))),
d_length_PN((int)(pow(2,degree_PN)-1))
{
set_output_multiple(d_length_PN); // noutput_items == multiple of
length
of PN sequence
}

void
dsss_spreading_blk_b::forecast(int noutput_items,gr_vector_int
&ninput_items_required){
assert(noutput_items % d_length_PN==0);

ninput_items_required[0]=noutput_items;
ninput_items_required[1]=noutput_items/d_length_PN;

}

int
dsss_spreading_blk_b::general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
//std::cout << "length of PN = "<< d_length_PN << std::endl;
const unsigned char *pn = (const unsigned char *)input_items[0];//
PN
const unsigned char *data = (const unsigned char *)input_items[1];//
data
unsigned char *out = (unsigned char *)output_items[0];
int data_items = ninput_items[1];
int pi,di;
for(pi=0,di=0;(pi<noutput_items);pi=pi+d_length_PN,di++){
unsigned char temp = data[di];
// std::cout << "input " << (int)temp << std::endl;
bool lsb=false;
if(temp & 0x01)
lsb=true;
else
lsb=false;
for(int j=0;j<d_length_PN;j++){
if(lsb)
out[pi+j] = pn[pi+j];
else
out[pi+j] = pn[pi+j]^0x01;
// std::cout << (int)out[pi+j] << std::endl;
}
//if(di==7)
// exit(0);
}
consume(0,noutput_items);
consume(1,noutput_items/d_length_PN);
}