OFDM

From SpenchWiki
Jump to: navigation, search

General

  • DVB-T Crest factor is greater than 8VSB (one reason why it wasn't adopted in the US).

Blind Analysis

  • Ning Han, Sung Sohn, Jae Moung, "A Blind OFDM Detection and Identification Method Based on Cyclostationarity for Cognitive Radio Application", IEICE Transactions on Communications, Volume E92-B, Number 6, pp. 2235-2238, June 2009.

DRM

Most common on HF is:

Class B
Modulation property Value
Un-guarded symbol time 21.33 ms
Sub-carrier spacing 46 7/8 Hz
Guard interval 5.33 ms
Total symbol duration 26.66 ms
Guard interval ratio 1/4
Symbols per frame 15
DRM OFDM signal clearly visible with distinctive sharp drop-off (there is a sonde operating on the righthand-side too, with decreasing sweep rate)

After capturing a DRM signal from Radio New Zealand International (above) and calculating the Cyclic Autocorrelation Function (CAF), it is confirmed to be class B:

CAF
Confirmed to be DRM signal due to symmetric peaks at lag 0 (peak at ~21.33, which is un-guarded symbol time)
At lag based on un-guarded symbol time, multiple peaks appear due pulse-shaping filter and multiple symbols in OFDM signal. First peak at ~37.84 Hz = almost 26.6 ms, which is total symbol duration.

The guard interval is the difference between the total symbol duration and the un-guarded symbol time. The sub-carrier spacing is the inverse of the un-guarded symbol time.

MATLAB

One can define a CAF calculation function like so (to do it properly you would use variable arguments, etc):

function [c,lag_labels,period_labels] = caf(x,start,len,tau,step,fft_range)

    decim = 1;
    len = len * decim;

    if (tau > start)
        error('tau > start');
    elseif ((start + tau + len) > length(x))
        error('length error')
    end

    c = [];
    x_labels = [];
    
    if fft_range > 0
        mid = fft_range;
    else
        mid = floor(len/decim/2);
    end
    
    period_labels = (-mid:mid)';
    
    for n = -tau:step:tau
        % Progress for long signals
        %if length(x) > (16384*2)
        %    disp(n);
        %end
        %n

        % If you want to zero-pad the signal
        %if n < 0
        %    t = cat(1, zeros(-n, 1), x(1:end+n));
        %elseif n > 0
        %    t = cat(1, x(n+1:end), zeros(n, 1));
        %else
        %    t = x
        %end

        t = x(start-n:start-n+len-1);
        %length(t)

        z = x(start:start+len-1).*conj(t);
        if decim > 1
            z = resample(z, 1, decim);
        end

        f = log10(abs(fftshift(fft(z))));
        %length(f)

        if fft_range > 0
            mid = floor(length(f)/2)+1;
            f = f(mid-fft_range:mid+fft_range);
        end
        
        c = cat(2, c, f);
        
        lag_labels = cat(1, x_labels, [n]);
    end

end

Then you would take the following steps to analyse a signal:

% This function can be found in an m file in the GNU Radio source tree
x = read_complex_binary('DRM.dat');
% Calculate the CAF (refer to function above):
[c,x_lab,y_lab] = caf(x,500000,16384, 500, 1, 150);
% Finally graph the CAF (and zoom in to show the peaks of interest):
mesh(x_lab*(1/20),(y_lab*(20000/16384)),c);
Top-down on CAF

Analysis in GNU Radio

One can use GRC (GNU Radio Companion) to construct something like this:

GRC flowgraph to determine OFDM signal properties

Run signal through Fast Auto-correlation to find un-guarded symbol duration. Set cyclo-lag to this value in samples (i.e. change Variable Delay at runtime). Run cyclo'd signal through another Fast Auto-correlation to find total symbol duration (including guard interval) - this is an FFT for (or a 'line' cut out of) one lag in the CAF above.

FAC with first peak at ~21.33 ms (un-guarded symbol time)

Generating the cyclo'd signal simply involves multiplying the signal by a delayed (lagged) version of itself. A new 'Variable Delay' block for GRC allows changing the delay (number of samples) during runtime.

CAF with first peak at ~26.66 ms (total symbol duration)

OFDM Mod GRC block

packet_mod_X(ofdm_mod(<options>)) - argument is 'packet_source'

packet_mod:

grc/grc_gnuradio/blks2/packet.py

packet_utils:

<core>/python/gnuradio/packet_utils.py

packet_mod_X

  • Default payload: 512 bytes (if supplied length is default 0, must be multiple of input stream size)
  • Input signature: X
  • Output signature: inherited from 'packet_source' stream #0 (complex for ofdm)

Starts packet encoder thread that packages incoming data into payload size and submits to 'packet_source' via 'send_pkt' call.

packet_utils.make_packet: preamble, access code, length of payload and CRC, (optionally whitened) payload with CRC-32, end byte.

  • 'preamble' is fixed.
  • 'access code' can be left as default (customisable preamble)

ofdm_mod:

<core>/python/gnuradio/blks2impl/ofdm.py

_pkt_input (ofdm_mapper_bcv) -> preambles (ofdm_insert_preamble) -> ifft (fft_vcc) -> cp_adder (ofdm_cyclic prefixer) -> scale (multiply_const_cc)

Padded preamble generation (for correlation in time domain):

  • zeros_on_left = ceil((FFT length - occupied tones) / 2.0)
  • ksfreq = take 'occupied symbols' length from known_symbols_4512_3 (randomly generated fixed list of 1/-1, 4512 items long (=4000+512 ?))
  • Each item (offset by zeros_on_left) that has an odd index is zeroed.
  • Padded preamble is FFT length, with zeros_on_left, then ksfreq hardcoded symbols, then remaining zeros on right.

ofdm_mapper_bcv: constellation based on modulation, message queue limit (default: 2), occupied tones, FFT length

ofdm_insert_preamble (insert 'pre-modulated' preamble symbols before each payload): FFT length, padded preambles

ofdm_cyclic prefixer (prefix output with CP length from end of input symbols): FFT length, symbol length (= FFT length + cyclic prefix length)

multiply_const_cc: 1.0 / sqrt(FFT length)