function ofdm_rx(filename, interleave_frames = 1)
ofdm_lib;
ldpc;
+ gp_interleaver;
more off;
% init modem
% load real samples from file
- Ascale= 2E5;
+ Ascale= 2E5*1.1491;
frx=fopen(filename,"rb"); rx = 2*fread(frx, Inf, "short")/4E5; fclose(frx);
Nsam = length(rx); Nframes = floor(Nsam/Nsamperframe);
prx = 1;
phase_est_pilot_log = [];
Terrs = Tbits = Terrs_coded = Tbits_coded = Tpackets = Tpacketerrs = 0;
Nbitspervocframe = 28;
+ Nerrs_coded_log = Nerrs_log = [];
% 'prime' rx buf to get correct coarse timing (for now)
states.foff_est_hz = foff_est;
end
+ if strcmp(state,'synced')
+ % we are in sync so log states
+
+ rx_np_log = [rx_np_log arx_np];
+ timing_est_log = [timing_est_log states.timing_est];
+ delta_t_log = [delta_t_log states.delta_t];
+ foff_est_hz_log = [foff_est_hz_log states.foff_est_hz];
+ phase_est_pilot_log = [phase_est_pilot_log; aphase_est_pilot_log];
+ end
+
if strcmp(state,'synced') && (frame_count == interleave_frames)
% de-interleave QPSK symbols
Nerrs_coded = sum(errors_coded);
Terrs_coded += Nerrs_coded;
Tbits_coded += code_param.data_bits_per_frame*interleave_frames;
- Nerrs_coded_log(f) = Nerrs_coded;
printf(" Nerrs_coded: %d\n", Nerrs_coded);
- % we are in sync so log states and bit/packet error stats
-
- rx_np_log = [rx_np_log arx_np];
- timing_est_log = [timing_est_log states.timing_est];
- delta_t_log = [delta_t_log states.delta_t];
- foff_est_hz_log = [foff_est_hz_log states.foff_est_hz];
- phase_est_pilot_log = [phase_est_pilot_log; aphase_est_pilot_log];
-
- % measure uncoded bit errors
+ % measure uncoded bit errors per modem frame
rx_bits_raw = [];
for s=1:Nsymbolsperinterleavedframe
rx_bits_raw = [rx_bits_raw qpsk_demod(rx_np(s))];
end
- errors = xor(tx_bits_raw, rx_bits_raw);
- Nerrs = sum(errors);
- Terrs += Nerrs;
- Nerrs_log(f) = Nerrs;
- Tbits += code_param.code_bits_per_frame*interleave_frames;
+ for ff=1:interleave_frames
+ st = (ff-1)*Nbitsperframe+1; en = st+Nbitsperframe-1;
+ errors = xor(tx_bits_raw(st:en), rx_bits_raw(st:en));
+ Nerrs = sum(errors);
+ Terrs += Nerrs;
+ Nerrs_log = [Nerrs_log Nerrs];
+ Tbits += Nbitsperframe;
+ end
% measure packet errors based on Codec 2 packet size
Tpacketerrs++;
end
Tpackets++;
+ Nerrs_coded_log = [Nerrs_coded_log Nvocpacketerrs];
end
frame_count = 0;
figure(5); clf;
subplot(211)
- title('Nerrs Log')
stem(Nerrs_log);
+ title('Uncoded errrors/modem frame')
subplot(212)
stem(Nerrs_coded_log);
+ title('Coded errrors/vocoder frame')
endfunction
% File based ofdm tx. Generate a file of ofdm samples, inclduing
% optional channel simulation.
+#{
+ Examples:
+
+ i) 4 frame interleaver, 10 seconds, AWGN channel at Eb/No=3dB
+
+ octave:4> ofdm_tx('awgn_ebno_3dB_700d.raw',4, 10,3);
+
+ ii) 4 frame interleaver, 10 seconds, HF channel at Eb/No=6dB
+
+ ofdm_tx('hf_ebno_6dB_700d.raw', 4, 10, 6, 'hf');
+#}
+
+
#{
TODO:
[ ] measure and report raw and coded BER
end
% not very pretty way to process analog signals with exactly the same channel
+ % todo: work out a cleaner way
+
+ analog_hack = 0; rx_filter = 0;
+ if analog_hack || rx_filter
+
+ % simulated SSB tx filter
+
+ [b, a] = cheby1(4, 3, [600, 2600]/(Fs/2));
+ h = freqz(b,a,(600:2600)/(Fs/(2*pi)));
+ filt_gain = (2600-600)/sum(abs(h) .^ 2); % ensures power after filter == before filter
+ end
- analog_hack = 0;
if analog_hack
+ % load analog signal and convert to complex
+
s = load_raw('../raw/ve9qrp_10s.raw')';
tx = hilbert(s);
+ % ssb tx filter
+
+ tx = filter(b,a,sqrt(filt_gain)*tx);
+
% normalise power to same as ofdm tx
nom_tx_pwr = 2/(Ns*(M*M)) + Nc/(M*M);
rx = real(rx) + noise;
printf("measured SNR: %3.2f dB\n", 10*log10(var(real(tx))/var(noise))+10*log10(4000) - 10*log10(3000));
- Ascale = 2E5;
+ if rx_filter
+ % ssb rx filter
+ rx = filter(b,a,sqrt(filt_gain)*rx);
+ end
+
+ % adjusted by experiment to match rms power of early test signals
+
+ Ascale = 2E5*1.1491;
+
frx=fopen(filename,"wb"); fwrite(frx, Ascale*rx, "short"); fclose(frx);
endfunction