Output of usrp_rx_cfile and Input of ATSC demodulator

All,

In the hopes of trying to understand the various aspects of GNU Radio
and the USRP hardware, I am trying to use the ATSC demodulator included
with GNU Radio to create an MPEG transport stream from the output of
usrp_rx_cfile.py. Something I know has been discussed many times on
this forum.

I am having a problems with disk writing not being able to keep up with
the high data rate, so I am trying to do a little manipulation of the IQ
data to get around this. What I am trying to do it get 8-bit samples
from the usrp (which my disk can keep up with) and then before I feed
that in to interp.py, I convert every pair of bytes to a complex.

So far this method has not yielded a single HDTV frame and I assume this
to be a problem with converting 8-bit samples to a complex. I
know I have a good signal because I can clearly see the 6 MHz channel
with strong pilot centered about my frequency using the fft utility, so
here are my questions (the answer to some of these may not really be
necessary to get this to work, but I ask them anyway so I am clear on
what is going on):

  1. What is going on with byte order? From looking at the output of
    usrp_rx_cfile.py, it looks like everything is little endian, but if this
    is the case, I do not see where the ATSC demodulator converts little
    endian to big endian to ensure for cross platform compatibility (the
    GNU Radio website does indicate that this is possible to run on windows
    and I have not found any information regarding byte order concerns). I
    am running Ubuntu on an x86 processor which is big endian and it sounds
    like most users machines are big endian, so is there some conversion
    going on or am I just reading the output of usrp_rx_cfile.py incorrectly
    (when set to stream complex floats)? Or is it that the USRP does send
    down floats in little endian and the ATSC demodulator expects that the
    input is of the same byte order of the machine it was compiled?

  2. What are the float values expected by the ATSC demodulator? In other
    words, what is the expected range of each float? Should they all be in
    the range (-1,1) or (0,1) or (min float value, max float value) or
    something else? It looks like the floats are all bounded to 2 bytes and
    the higher two bytes are just not used.

  3. When converting an 8-bit sample to a float, do I need to scale it or
    just cast it to a float? So if I have a byte with the value of 100,
    could I just something like “scale = 100/255; i = FLOAT_MAX * scale?”
    Looking at some of the conversion methods included, it seems that a char
    gets simply casted to a float, but I believe this would have a negative
    effect since it causes all the amplitudes to appear weak.

  4. When I specify 8-bit samples from usrp_rx_cfile.py, are these bytes
    signed or unsigned? I find this important because if I want to scale
    each byte to a float, instead of just casting, I would possibly need to
    do some bit masking to account for this.

Any incite in to these questions would be most appreciated!

Thanks,
Brandon

Wuest Brandon-WTVR47 schrieb:

the IQ data to get around this. What I am trying to do it get 8-bit
samples from the usrp (which my disk can keep up with) and then before
I feed that in to interp.py, I convert every pair of bytes to
a complex.

Perhaps I missed something here… if you are having problems recording
2 ‘8-bit’ integers, why would converting those integers to floats, that
is creating now 2 4 byte quantities… improve performance in any way.

Back when I worried about such things, I usually thought about
maintaining everything in ‘integer’ form, and should I have needed a
‘FFT’, I would start thinking
about Galois Fields, prime generator polynomials… and the like, but
stay with integers…

John C…

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Wuest Brandon-WTVR47 wrote:

I am having a problems with disk writing not being able to keep up with
the high data rate, so I am trying to do a little manipulation of the IQ
data to get around this. What I am trying to do it get 8-bit samples
from the usrp (which my disk can keep up with) and then before I feed
that in to interp.py, I convert every pair of bytes to a complex.

A logical approach if your disk can’t handle 32MBps linear write.

I’ll answer question #0 first:

For converting pairs of bytes to complex, this might seem a bit (really,
a lot) silly, but a simple way to do it in GNU Radio would be

gr.file_source(gr.sizeof_char,“file”) →
gr.char_to_float() →
gr.float_to_short() →
gr.interleaved_short_to_complex()

You could also write a gr.interleaved_char_to_complex() block (which
appears to not exist in gnuradio-core/src/lib/general) which would be a
MUCH better solution but would require effort :-D.

down floats in little endian and the ATSC demodulator expects that the
input is of the same byte order of the machine it was compiled?

Source files are assumed to be in local-Endian, and sink files are
created local-Endian. Cross-platform is in the eye of the user :-D.

Also, I challenge your assertion that Ubuntu on an x86 processor is big
Endian. Endian-ness is a function of the architecture (except some crazy
and/or cool chips that have an Endian-switch like I think some older
Macs).

  1. What are the float values expected by the ATSC demodulator? In other
    words, what is the expected range of each float? Should they all be in
    the range (-1,1) or (0,1) or (min float value, max float value) or
    something else? It looks like the floats are all bounded to 2 bytes and
    the higher two bytes are just not used.

No idea

  1. When converting an 8-bit sample to a float, do I need to scale it or
    just cast it to a float? So if I have a byte with the value of 100,
    could I just something like “scale = 100/255; i = FLOAT_MAX * scale?”
    Looking at some of the conversion methods included, it seems that a char
    gets simply casted to a float, but I believe this would have a negative
    effect since it causes all the amplitudes to appear weak.

Usually you’d just cast to a float. The demodulator should presumably
handle low-amplitude signals. But see my answer to (2).

  1. When I specify 8-bit samples from usrp_rx_cfile.py, are these bytes
    signed or unsigned? I find this important because if I want to scale
    each byte to a float, instead of just casting, I would possibly need to
    do some bit masking to account for this.

Signed.

Good luck!

Dan
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHTzlty9GYuuMoUJ4RAvDdAJ0ez/tzvBN4WYBM54dqsus2jSbo3gCgm3pv
ot0SaQ5gcSorrETliLcaulI=
=t79U
-----END PGP SIGNATURE-----

On Nov 29, 2007 5:13 PM, Dan H. [email protected]
wrote:

A logical approach if your disk can’t handle 32MBps linear write.

You could also write a gr.interleaved_char_to_complex() block (which
appears to not exist in gnuradio-core/src/lib/general) which would be a
MUCH better solution but would require effort :-D.

So I had this idea just sitting here after coming home from work and I
pose it as a question - why do the stored complex samples have to be
stored as complex?

Because they are orthogonal to each other, shouldn’t there be a simple
way to generate real samples (possibly at some simple intermediate
frequency instead of at baseband) and automatically half the number of
samples that need to be written? Could you use a simple scheme of
{+1, 0, -1, 0} for your IF for mixing and still retain most of the
information?

Has anyone tried something like this to reduce the amount of data
required for sustained writes? What do people think of the
feasibility of such a system?

Brian

When you specify a bit width of 8, does that not pack them in to a
single byte rather than an integer? If I am correct in this, then I am
effectively cutting my data rate by 4, which is a huge boost. Though I
will loose some value due to quantization noise, the point is to cut
down the chance of an under run, while maintaining the correct format
for the ATSC demodulator.

Just as if you use the flag -s, you get 16-bit values contained within a
short (2 bytes), not an entire word.

Do you know if the USRP is in fact little endian? I wrote a little C
program to test the endian-ness of my machine (which I am sure everyone
did in CS 101) and its big endian.

Endian-ness is based purely off the processor and not the OS right?
Sorry for the somewhat non-related SDR question, I generally work with
Java, so I sometimes forget about those silly low level details :).

The USRP transfers data in little endian order.

It is based off the processor architecture.

  • George

On Thu, Nov 29, 2007 at 05:51:30PM -0500, Wuest Brandon-WTVR47 wrote:

Do you know if the USRP is in fact little endian? I wrote a little C
program to test the endian-ness of my machine (which I am sure everyone
did in CS 101) and its big endian.

Endian-ness is based purely off the processor and not the OS right?
Sorry for the somewhat non-related SDR question, I generally work with
Java, so I sometimes forget about those silly low level details :).

Raw data from the USRP is little endian. If you use
usrp.source_c(…) it’s converted to native complex in the
interface code.

Eric

On Thu, Nov 29, 2007 at 05:56:02PM -0500, George N. wrote:

The USRP transfers data in little endian order.

Correct.

It is based off the processor architecture.

We decided to ship data across the USB in little-endian format because
of the widespread use of x86 machines. The host library handles the
conversion for big-endian hosts.

Eric