OFDM
Contents
General
 DVBT 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 E92B, Number 6, pp. 22352238, June 2009.
 Find subcarrier spacing and duration of guard interval.
 Exploit cyclic prefix and cyclostationarity of OFDM due to transmitter pulseshaping filter.
DRM
Most common on HF is:
Modulation property  Value 

Unguarded symbol time  21.33 ms 
Subcarrier 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 
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:
The guard interval is the difference between the total symbol duration and the unguarded symbol time. The subcarrier spacing is the inverse of the unguarded 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 zeropad 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(startn:startn+len1);
%length(t)
z = x(start:start+len1).*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(midfft_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);
Analysis in GNU Radio
One can use GRC (GNU Radio Companion) to construct something like this:
Run signal through Fast Autocorrelation to find unguarded symbol duration. Set cyclolag to this value in samples (i.e. change Variable Delay at runtime). Run cyclo'd signal through another Fast Autocorrelation 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.
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.
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 CRC32, 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 'premodulated' 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)
