Gr_unpack_k_bits_bb, its inverse, and higher order constellations

Hi list,

I have been trying to send and receive higher order constellations than
bpsk (qpsk, qam16, …). The way I’m currently implementing this (in
c++) is that I have a custom “pack_k_bits_bb(int bits_per_symbol)”-
block and then feed the result into a “gr_chunks_to_symbols_bc”- block,
and then onward in the transmitting chain.

On the receiving side, I use a “constellation_decoder_cb”- block
followed by a “gr_unpack_k_bits_bb”- block to get the bits back.

This approach assumes that there are less than 8 bits per symbol, and
that the input to the transmitting chain is unpacked bytes, which is
also produced by the receiver.

The question is now, how do you produce constellations with more than 1
bit per symbol? Is there a better way to do this? Sure if one want to,
for instance, read from a file/device the input should be packed bytes,
but if the input to the transmitting chain is a “gr_scrambler_bb”-
block… This is one way of doing it.

Comments and suggestions on how to do this in other ways are most
appreciated.

BR
//Mattias

On Wed, Mar 03, 2010 at 11:25:56AM +0100, Mattias K. wrote:

This approach assumes that there are less than 8 bits per symbol, and
that the input to the transmitting chain is unpacked bytes, which is
also produced by the receiver.

The question is now, how do you produce constellations with more than 1
bit per symbol? Is there a better way to do this? Sure if one want to,
for instance, read from a file/device the input should be packed bytes,
but if the input to the transmitting chain is a “gr_scrambler_bb”-
block… This is one way of doing it.

I assume that you mean 1 byte per symbol.
I suggest that you create *_ci and *_ii versions that handle 32-bits.

Eric

Eric B. wrote:

I assume that you mean 1 byte per symbol.
I suggest that you create *_ci and *_ii versions that handle 32-bits.

Eric
You are correct, one byte per symbol. Or one symbol per byte, whichever
way one wants to look at it.
To clarify what the custom block does is that it takes K bytes with 1
significant bit (in lsb, from a glfsr or similar) and turns it into 1
byte with K significant bits. Then it’s just to feed these new, “packed”
(is this the word for it?), bytes into the chunks_to_symbols_bc- block,
producing one symbol for every byte.

Is this really stupid, or has it just not been done yet? I assume that
there are more people working with more signal- points than two in their
constellations. But at the same time it seems like I’m wasting a lot of
resources on copying bytes with only two or three (qpsk, qam16)
significant bits in them…

//Mattias

Tom R. wrote:

way one wants to look at it.
significant bits in them…

Tom

I know of them, and have looked at them, but nothing more. Since I don’t
speak python very well, I try to do everything in c++.

I have tried to use pilots mixed in every few data- symbols and
compensate the data- symbols using these known symbols. I’m getting kind
of good results, although I think the custom early/late gate sampler I
wrote has a settling time way to long (between 900 and 3000 symbols
depending on which constants I put in). I’ll try to rewrite the M&M-
sync- block to utilize the slicer_45deg(), and see what results I get
with that. From what I can tell from the paper pointed to by the header-
file, the optimized M&M- loop should be able to handle at least QPSK,
and have a way shorter settling time than 900 symbols.

I think the pilot- compensation code should still work and compensate
any screw to the constellation.

I’m getting all exited just writing about it :wink: I’ll let you know how it
goes.
//Mattias

On Thu, Mar 4, 2010 at 11:38 AM, Mattias K. [email protected] wrote:

You are correct, one byte per symbol. Or one symbol per byte, whichever
resources on copying bytes with only two or three (qpsk, qam16)
but I think these do what you want.
depending on which constants I put in). I’ll try to rewrite the M&M-
//Mattias
Matt and I wrote a resampler based on polyphase filterbanks a few
months ago. It’s called gr_pfb_clock_sync_xxf (in the filter
directory). It works really well for any PAM signal (we’ve tested it
with PSK and QAMs successfully). You can see how its used in the new
dbpsk2.py and dqpsk2.py files.

Tom

On Thu, Mar 4, 2010 at 10:28 AM, Mattias K. [email protected] wrote:

(is this the word for it?), bytes into the chunks_to_symbols_bc- block,
producing one symbol for every byte.

Is this really stupid, or has it just not been done yet? I assume that
there are more people working with more signal- points than two in their
constellations. But at the same time it seems like I’m wasting a lot of
resources on copying bytes with only two or three (qpsk, qam16)
significant bits in them…

//Mattias

Have you looked at
gnuradio-core/src/python/gnuradio/blks2impl/dqpsk.py (and qam8, qam16,
qam64, and qam256.py)? They handle the modulation and demodulation
parts of the TX and RX. We don’t have a good synchronization scheme,
but I think these do what you want.

Tom

Mattias K. wrote:

Eric B. wrote:

there are more people working with more signal- points than two in their
Have you looked at
I know of them, and have looked at them, but nothing more. Since I don’t
and have a way shorter settling time than 900 symbols.
Matt and I wrote a resampler based on polyphase filterbanks a few
with the M&M- loop as I hoped… It might have something to do with the
Yes, at this point, the constellation is locked, but it’s just locked
Lines 49 and 57 in gr_pbf_clock_sync_ccf.cc,
Which is new to me… I have isolated it to the the gr_pbf_sync_ccf-

is no input- signal to the usrp, but when that comes on, the program
almost immediately exits with the above error.

I guess I have done something wrong, since this code should be tested by
now, right?

Best regards,
//Mattias

Sorry, I just saw that I wrote the last message off- list.

Anyway, I have searched some more in the causes of this error. I took
the easy way out and looked in gr_buffer.h at line 127. and Changed
this:
Approximately around lines 115->130 in gr_buffer.h
unsigned index_add (unsigned a, unsigned b){
unsigned s = a + b;
/if (s >= d_bufsize)
s -= d_bufsize;
/
while(s>=d_bufsize){
s-=d_bufsize;
}
assert (s < d_bufsize);
return s;
}

I assume this is not the way to do this, but it gets rid of the error-
message… But since I have changed in the library to make this specific
block not produce an error… It just seems like doing things backwards.
But then again, this code- change assures that s<d_bufsize, but is it
always correct to do this? I guess not, but I’m not sure.

It still produces segmentation faults though, which are off unclear
origin. It wasn’t there before I tried the gr_make_pfb_clock_sync_ccf -
block, but than again, it might be something hidden in my custom code
that has popped out on the surface all of the sudden when the soundings
to these blocks have changed.

Regards
//Mattias

On Fri, Mar 05, 2010 at 04:26:34PM +0100, Mattias K. wrote:

/*if (s >= d_bufsize)

block not produce an error… It just seems like doing things backwards.
But then again, this code- change assures that s<d_bufsize, but is it
always correct to do this? I guess not, but I’m not sure.

index_add is correct as originally written.

I suspect that pfb_clock_sync_ccf has a problem in it.

It looks like it only works if the number of output streams is 1 or 4,
but not 2 or 3. It needs to override check_topology to enforce this.

The two occurences of:

if(output_items.size() > 2) {
  ...
}

should probably be changed to: if (output_items.size() == 4)

It also looks like it’s leaking d_diff_filters (should delete in the
destructor).

Eric

On Fri, Mar 05, 2010 at 06:34:48PM -0800, Eric B. wrote:

unsigned s = a + b;
message… But since I have changed in the library to make this specific

The two occurences of:

if(output_items.size() > 2) {
  ...
}

should probably be changed to: if (output_items.size() == 4)

It also looks like it’s leaking d_diff_filters (should delete in the
destructor).

Mattias,

I’ve just committed a fix to master for the items I describe above.
When you get a chance, can you please update and try your test again?

Thanks!
Eric