1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
% ofdm_rx.m
% David Rowe May 2018
%
% OFDM file based , uncoded rx to unit test core OFDM modem. See also
% ofdm_ldpc_rx which includes LDPC and interleaving, and ofdm_demod.c
function ofdm_rx(filename, mode="700D", error_pattern_filename)
ofdm_lib;
more off;
% init modem
[bps Rs Tcp Ns Nc] = ofdm_init_mode(mode);
states = ofdm_init(bps, Rs, Tcp, Ns, Nc);
print_config(states);
ofdm_load_const;
states.verbose = 0;
% load real samples from file
Ascale = states.amp_scale/2; % as input is a real valued signal
frx=fopen(filename,"rb"); rx = fread(frx, Inf, "short")/Ascale; fclose(frx);
Nsam = length(rx); Nframes = floor(Nsam/Nsamperframe);
prx = 1;
% OK re-generate tx frame for BER calcs
tx_bits = create_ldpc_test_frame(states, coded_frame=0);
% init logs and BER stats
rx_bits = []; rx_np_log = []; timing_est_log = []; delta_t_log = []; foff_est_hz_log = [];
phase_est_pilot_log = []; sig_var_log = []; noise_var_log = []; channel_est_log = [];
Terrs = Tbits = Terrs_coded = Tbits_coded = Tpackets = Tpacketerrs = frame_count = 0;
Nbitspervocframe = 28;
Nerrs_coded_log = Nerrs_log = [];
error_positions = [];
% 'prime' rx buf to get correct coarse timing (for now)
prx = 1;
nin = Nsamperframe+2*(M+Ncp);
%states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx(prx:nin);
%prx += nin;
states.verbose = 1;
Nerrs = 0; rx_uw = zeros(1,states.Nuwbits);
% main loop ----------------------------------------------------------------
for f=1:Nframes
% insert samples at end of buffer, set to zero if no samples
% available to disable phase estimation on future pilots on last
% frame of simulation
lnew = min(Nsam-prx,states.nin);
rxbuf_in = zeros(1,states.nin);
if lnew
rxbuf_in(1:lnew) = rx(prx:prx+lnew-1);
end
prx += states.nin;
if strcmp(states.sync_state,'search')
[timing_valid states] = ofdm_sync_search(states, rxbuf_in);
end
if strcmp(states.sync_state,'synced') || strcmp(states.sync_state,'trial')
[rx_bits states aphase_est_pilot_log arx_np arx_amp] = ofdm_demod(states, rxbuf_in);
[rx_uw payload_syms payload_amps txt_bits] = disassemble_modem_frame(states, arx_np, arx_amp);
errors = xor(tx_bits, rx_bits);
Nerrs = sum(errors);
aber = Nerrs/Nbitsperframe;
% 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];
sig_var_log = [sig_var_log states.sig_var];
noise_var_log = [noise_var_log states.noise_var];
channel_est_log = [channel_est_log; states.achannel_est_rect];
% measure uncoded bit errors on modem frame
Nerrs_log = [Nerrs_log Nerrs];
Terrs += Nerrs;
Tbits += Nbitsperframe;
frame_count++;
end
states = sync_state_machine(states, rx_uw);
if states.verbose
printf("f: %2d nin: %4d state: %-10s uw_errors: %2d %1d pbw: %-4s Nerrs: %3d foff: %5.1f clkOff: %5.0f\n",
f, states.nin, states.last_sync_state, states.uw_errors, states.sync_counter, states.phase_est_bandwidth, Nerrs,
states.foff_est_hz, states.clock_offset_est*1E6);
end
% act on any events returned by state machine
if states.sync_start
Nerrs_log = [];
Terrs = Tbits = frame_count = 0;
rx_np_log = [];
sig_var_log = []; noise_var_log = [];
end
end
printf("\nBER..: %5.4f Tbits: %5d Terrs: %5d\n", Terrs/(Tbits+1E-12), Tbits, Terrs);
% If we have enough frames, calc BER discarding first few frames where freq
% offset is adjusting
Ndiscard = 20;
if frame_count > Ndiscard
Terrs -= sum(Nerrs_log(1:Ndiscard)); Tbits -= Ndiscard*Nbitsperframe;
printf("BER2.: %5.4f Tbits: %5d Terrs: %5d\n", Terrs/Tbits, Tbits, Terrs);
end
%EsNo_est = mean(sig_var_log(floor(end/2):end))/mean(noise_var_log(floor(end/2):end));
EsNo_est = mean(sig_var_log)/mean(noise_var_log);
EsNo_estdB = 10*log10(EsNo_est);
SNR_estdB = EsNo_estdB + 10*log10(Nc*Rs/3000);
printf("Es/No est dB: % -4.1f SNR3k: %3.2f %f %f\n", EsNo_estdB, SNR_estdB, mean(sig_var_log), mean(noise_var_log));
figure(1); clf;
plot(rx_np_log,'+');
plot(rx_np_log(floor(end/2):end),'+');
mx = 2*max(abs(rx_np_log));
axis([-mx mx -mx mx]);
title('Scatter');
figure(2); clf;
plot(phase_est_pilot_log(:,2:Nc),'g+', 'markersize', 5);
title('Phase est');
axis([1 length(phase_est_pilot_log) -pi pi]);
figure(3); clf;
subplot(211)
stem(delta_t_log)
title('delta t');
subplot(212)
plot(timing_est_log);
title('timing est');
figure(4); clf;
plot(foff_est_hz_log)
mx = max(abs(foff_est_hz_log))+1;
axis([1 max(Nframes,2) -mx mx]);
title('Fine Freq');
ylabel('Hz')
figure(5); clf;
stem(Nerrs_log);
title('Errors/modem frame')
axis([1 length(Nerrs_log) 0 Nbitsperframe*rate/2]);
figure(6); clf;
plot(10*log10(sig_var_log),'b;Es;');
hold on;
plot(10*log10(noise_var_log),'r;No;');
snr_estdB = 10*log10(sig_var_log) - 10*log10(noise_var_log) + 10*log10(Nc*Rs/3000);
snr_smoothed_estdB = filter(0.1,[1 -0.9],snr_estdB);
plot(snr_smoothed_estdB,'g;SNR3k;');
hold off;
title('Signal and Noise Power estimates');
if nargin == 3
fep = fopen(error_pattern_filename, "wb");
fwrite(fep, error_positions, "short");
fclose(fep);
end
endfunction
|