Tuesday, February 15, 2011

GNU Radio TX/RX text via DQPSK

I am attempting to transfer a text file using the USRP an DQPSK modulation. I connected constellation sinks to both the transmit and receive sides.

TX constellation:


RX constellation:

I am using a packet encoder/decoder on both ends, but the packet_decoder is not producing any output.

UPDATE: So on the RX side it appears my gain was too high. After adjusting it I get much better results.

Monday, February 14, 2011

GNU Radio modulation

Looking at gnuradio-examples/python/digital/tx_voice.py....

self.txpath = usrp_transmit_path.usrp_transmit_path(modulator_class, options)

Leads me to usrp_transimit_path.py, which sets some USRP sink options, then passes the work to transmit_path.py.

The options passed to transmit_path.py include:

  • verbose
  • tx_amplitude
  • bitrate
  • samples_per_symbol

...and then the 'modulator class':

self._modulator_class = modulator_class

    # Get mod_kwargs
    mod_kwargs = \
        self._modulator_class.extract_kwargs_from_options(options)
    
    # transmitter
    modulator = self._modulator_class(**mod_kwargs)
    self.packet_transmitter = \
        blks2.mod_pkts(modulator,
                       access_code=None,
                       msgq_limit=4,
                       pad_for_usrp=True)

Then you connect the 'packet_transmitter', amplitude, and transmit path together.

self.connect(self.packet_transmitter, self.amp, self)

    ...

def send_pkt(self, payload='', eof=False):
    """
    Calls the transmitter method to send a packet
    """
    return self.packet_transmitter.send_pkt(payload, eof)

gnuradio-3.3.0/gnuradio-core/src/python/gnuradio/blks2impl/pkt.py: blks2.mod_pkts


class mod_pkts gets passed an instance of a modulator class (gr_block of heir_block2). It then simply connects a packet input block (gr_message_source(sizeof char, msgq_limit):

self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit)
    self.connect(self._pkt_input, self._modulator, self)



Modulation classes (tx_voice.py):

from gnuradio import gr, gru, modulation_utils
...
mods = modulation_utils.type_1_mods()
...
    for mod in mods.values():
        mod.add_options(expert_grp)
...
# pass it down: tx_voice.py -> usrp_transmit_path.py -> transmit_path.py -> pkt.py
tb = my_top_block(mods[options.modulation], options)

This particular example generated packets from a message queue attached to a voice coder:

from gnuradio.vocoder import gsm_full_rate
...
voice_coder = gsm_full_rate.encode_sp()

The corresponding C++ block, gsm_fr_encode_sp, has a simple work function:

for (int i = 0; i < noutput_items; i++){
    gsm_encode (d_gsm, const_cast(in), out);
    in += GSM_SAMPLES_PER_FRAME;
    out += sizeof (gsm_frame);
  }

This references C code which does the GSM (de/en)coding.



Here are the modulators available in tx_voice.py:

gnuradio.blks2impl.cpm.cpm_mod
gnuradio.blks2impl.d8psk.d8psk_mod
gnuradio.blks2impl.qam8.qam8_mod
gnuradio.blks2impl.dbpsk.dbpsk_mod
gnuradio.blks2impl.dqpsk.dqpsk_mod
gnuradio.blks2impl.gmsk.gmsk_mod

Implemented as separate Python files in gnuradio-core/src/python/gnuradio/blks2impl. The other blks2 folder ties it all together.

Friday, February 11, 2011

hoc: hoc 4 completed

...on Friday after work? What's wrong with me?

Still includes the modulus operator but I need to fix the previous result command (?).

hoc: hoc3 completed

hoc3 is complete, minus the exercises. I nearly bashed my head into the wall trying to track down the following segfault:

yyval.sym = s;

yyval should be yylval!?!? yyval is defined by yacc, and this is a valid statement. Ugh.

[tja@tja-desktop hoc3]$ ./hoc3
1.5^2.3
 2.5410306
exp(2.3*log(1.5))
 2.5410306
sin(PI/2)
 1
atan(1)*DEG
 45
?
 45

Again, '?' will print the last computed value.

TODO:


  1. 8-6: add support for built-ins with multiple parameters.
  2. 8-7: facility to execute commands (done?)
  3. 8-8: revise math.c to use a table instead

Thursday, February 10, 2011

GNU Radio OFDM Python

from gnuradio import blks2

The code for the module 'blks2' actually resides in a directory 'blk2impl'. It is renamed by the SWIG glue.

./gnuradio-3.3.0/gnuradio-core/src/python/gnuradio/blks2impl/ofdm.py

ofdm.py defines an ofdm_mod class which "modulates an OFDM stream." This program in particular uses the C++ blocks gr_ofdm_mapper_bcv, gr_ofdm_insert_preamble, gr_fft_vcc, gr_ofdm_cyclic_prefixer, and gr_multiply_const_cc.

OFDM modulation:

self._pkt_input = gr.ofdm_mapper_bcv(rotated_const, msgq_limit, options.occupied_tones, options.fft_length)
        
self.preambles = gr.ofdm_insert_preamble(self._fft_length, padded_preambles)
self.ifft = gr.fft_vcc(self._fft_length, False, win, True)
self.cp_adder = gr.ofdm_cyclic_prefixer(self._fft_length, symbol_length)
self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length))
        
self.connect((self._pkt_input, 0), (self.preambles, 0))
self.connect((self._pkt_input, 1), (self.preambles, 1))
self.connect(self.preambles, self.ifft, self.cp_adder, self.scale, self)

ofdm.py also has the ofdm_demod class:

GNU Radio OFDM C++ blocks

Descriptions from the gnuradio-3.3.0 documentation.

gr_ofdm_demapper_vcb.


take a stream of vectors in from an FFT and demodulate to a stream of bits. Abstract class must be subclassed with specific mapping.

gr_ofdm_frame_aquisition

take a vector of complex constellation points in from an FFT and performs a correlation and equalization.
This block takes the output of an FFT of a received OFDM symbol and finds the start of a frame based on two known symbols. It also looks at the surrounding bins in the FFT output for the correlation in case there is a large frequency shift in the data. This block assumes that the fine frequency shift has already been corrected and that the samples fall in the middle of one FFT bin.
It then uses one of those known symbols to estimate the channel response over all subcarriers and does a simple 1-tap equalization on all subcarriers. This corrects for the phase and amplitude distortion caused by the channel.

gr_ofdm_mapper_bcv


take a stream of bytes in and map to a vector of complex constellation points suitable for IFFT input to be used in an ofdm modulator. Abstract class must be subclassed with specific mapping.

gr_ofdm_frame_sink


Takes an OFDM symbol in, demaps it into bits of 0's and 1's, packs them into packets, and sends to to a message queue sink.

NOTE: The mod input parameter simply chooses a pre-defined demapper/slicer. Eventually, we want to be able to pass in a reference to an object to do the demapping and slicing for a given modulation type.

gr_ofdm_insert_preamble


insert "pre-modulated" preamble symbols before each payload.

input 1: stream of vectors of gr_complex [fft_length]
These are the modulated symbols of the payload.
input 2: stream of char. The LSB indicates whether the corresponding
symbol on input 1 is the first symbol of the payload or not.
It's a 1 if the corresponding symbol is the first symbol,
otherwise 0.
N.B., this implies that there must be at least 1 symbol in the payload.
output 1: stream of vectors of gr_complex [fft_length]
These include the preamble symbols and the payload symbols.
output 2: stream of char. The LSB indicates whether the corresponding
symbol on input 1 is the first symbol of a packet (i.e., the
first symbol of the preamble.) It's a 1 if the corresponding
symbol is the first symbol, otherwise 0.

Parameters:
fft_length length of each symbol in samples.
preamble vector of symbols that represent the pre-modulated preamble.

gr_ofdm_cyclic_prefixer


adds a cyclic prefix vector to an input size long ofdm symbol(vector) and converts vector to a stream output_size long.

gr_ofdm_sampler


"Does the rest of the OFDM stuff"

Wednesday, February 9, 2011

C++ pseudo static map initialization

std::pair map_data[] = {
    std::make_pair(1, "a"),
    std::make_pair(2, "b"),
    std::make_pair(3, "c")
};

std::map my_map(map_data,
    map_data + sizeof map_data / sizeof map_data[0]);