From e0492de41b9f0c6eb1c133be559dcd9311dcf317 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 19 May 2012 10:48:22 +0000 Subject: [PATCH] SNR estimation feature for modem tested in Octave and C git-svn-id: https://svn.code.sf.net/p/freetel/code@484 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/README_fdmdv.txt | 2 +- codec2-dev/octave/fdmdv.m | 70 +++++++++++++++- codec2-dev/octave/fdmdv_demod.m | 20 ++++- codec2-dev/octave/fdmdv_demod_c.m | 4 + codec2-dev/octave/fdmdv_ut.m | 34 ++++++-- codec2-dev/octave/phase2.m | 15 +++- codec2-dev/octave/plamp.m | 1 + codec2-dev/octave/tfdmdv.m | 17 +++- codec2-dev/src/c2sim.c | 3 + codec2-dev/src/fdmdv.c | 128 +++++++++++++++++++++++++++--- codec2-dev/src/fdmdv.h | 2 +- codec2-dev/src/fdmdv_demod.c | 4 +- codec2-dev/src/fdmdv_internal.h | 9 +++ codec2-dev/unittest/tfdmdv.c | 9 +++ 14 files changed, 287 insertions(+), 31 deletions(-) diff --git a/codec2-dev/README_fdmdv.txt b/codec2-dev/README_fdmdv.txt index 9c61bc60..fc091018 100644 --- a/codec2-dev/README_fdmdv.txt +++ b/codec2-dev/README_fdmdv.txt @@ -195,4 +195,4 @@ TODO + e.g. hang on thru the fades? [ ] PAPR idea + automatically tweak phases to reduce PAPR, e.g. slow variations in freq... - +[ ] why is pilot noise_est twice as big as other carriers diff --git a/codec2-dev/octave/fdmdv.m b/codec2-dev/octave/fdmdv.m index 303b172b..432be81a 100644 --- a/codec2-dev/octave/fdmdv.m +++ b/codec2-dev/octave/fdmdv.m @@ -30,6 +30,7 @@ global P = 4; % oversample factor used for rx symbol filtering global Nfilter = Nsym*M; global Nfiltertiming = M+Nfilter+M; alpha = 0.5; +global snr_coeff = 0.9 % SNR est averaging filter coeff % root raised cosine (Root Nyquist) filter @@ -399,7 +400,7 @@ endfunction % convert symbols back to an array of bits -function [rx_bits sync_bit f_err] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation) +function [rx_bits sync_bit f_err phase_difference] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation) global Nc; global Nb; global Nb; @@ -408,6 +409,7 @@ function [rx_bits sync_bit f_err] = qpsk_to_bits(prev_rx_symbols, rx_symbols, mo % extra 45 degree clockwise lets us use real and imag axis as % decision boundaries + phase_difference = zeros(Nc+1,1); phase_difference(1:Nc) = rx_symbols(1:Nc) .* conj(prev_rx_symbols(1:Nc)) * exp(j*pi/4); % map (Nc,1) DQPSK symbols back into an (1,Nc*Nb) array of bits @@ -432,7 +434,7 @@ function [rx_bits sync_bit f_err] = qpsk_to_bits(prev_rx_symbols, rx_symbols, mo % Extract DBPSK encoded Sync bit - phase_difference(Nc+1) = rx_symbols(Nc+1) .* conj(prev_rx_symbols(Nc+1)); + phase_difference(Nc+1,1) = rx_symbols(Nc+1) .* conj(prev_rx_symbols(Nc+1)); if (real(phase_difference(Nc+1)) < 0) sync_bit = 1; f_err = imag(phase_difference(Nc+1)); @@ -441,6 +443,10 @@ function [rx_bits sync_bit f_err] = qpsk_to_bits(prev_rx_symbols, rx_symbols, mo f_err = -imag(phase_difference(Nc+1)); end + % pilot carrier gets an extra pi/4 rotation to make it consistent with + % other carriers, as we need it for snr_update and scatter diagram + + phase_difference(Nc+1) *= exp(j*pi/4); else % map (Nc,1) QPSK symbols back into an (1,Nc*Nb) array of bits @@ -451,6 +457,65 @@ function [rx_bits sync_bit f_err] = qpsk_to_bits(prev_rx_symbols, rx_symbols, mo endfunction +% given phase differences update estimates of signal and noise levels + +function [sig_est noise_est] = snr_update(sig_est, noise_est, phase_difference) + global snr_coeff; + global Nc; + + % mag of each symbol is distance from origin, this gives us a + % vector of mags, one for each carrier. + + s = abs(phase_difference); + + % signal mag estimate for each carrier is a smoothed version + % of instantaneous magntitude, this gives us a vector of smoothed + % mag estimates, one for each carrier. + + sig_est = snr_coeff*sig_est + (1 - snr_coeff)*s; + + % noise mag estimate is distance of current symbol from average + % location of that symbol. We reflect all symbols into the first + % quadrant for convenience. + + refl_symbols = abs(real(phase_difference)) + j*abs(imag(phase_difference)); + n = abs(exp(j*pi/4)*sig_est - refl_symbols); + + % noise mag estimate for each carrier is a smoothed version of + % instantaneous noise mag, this gives us a vector of smoothed + % noise power estimates, one for each carrier. + + noise_est = snr_coeff*noise_est + (1 - snr_coeff)*n; +endfunction + + +% calculate current SNR estimate (3000Hz noise BW) + +function snr_dB = calc_snr(sig_est, noise_est) + global Rs; + + % find total signal power by summing power in all carriers + + S = sum(sig_est .^2); + SdB = 10*log10(S); + + % Average noise mag across all carriers and square to get an average + % noise power. This is an estimate of the noise power in Rs = 50Hz of + % BW (note for raised root cosine filters Rs is the noise BW of the + % filter) + + N50 = mean(noise_est).^2; + N50dB = 10*log10(N50); + + % Now multiply by (3000 Hz)/(50 Hz) to find the total noise power in + % 3000 Hz + + N3000dB = N50dB + 10*log10(3000/Rs); + + snr_dB = SdB - N3000dB; + +endfunction + % returns nbits from a repeating sequence of random data function bits = get_test_bits(nbits) @@ -868,4 +933,3 @@ current_test_bit = 1; global rx_test_bits_mem; rx_test_bits_mem = zeros(1,Ntest_bits); - diff --git a/codec2-dev/octave/fdmdv_demod.m b/codec2-dev/octave/fdmdv_demod.m index 0ef4f673..489a616c 100644 --- a/codec2-dev/octave/fdmdv_demod.m +++ b/codec2-dev/octave/fdmdv_demod.m @@ -30,10 +30,18 @@ function fdmdv_demod(rawfilename, nbits, pngname) test_frame_sync_log = []; test_frame_sync_state = 0; + % SNR states + + sig_est = zeros(Nc+1,1); + noise_est = zeros(Nc+1,1); + + % logs of various states for plotting + rx_symbols_log = []; rx_timing_log = []; foff_log = []; rx_fdm_log = []; + snr_est_log = []; % misc states @@ -92,7 +100,10 @@ function fdmdv_demod(rawfilename, nbits, pngname) else rx_symbols_log = [rx_symbols_log rx_symbols]; endif - [rx_bits sync f_err] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation); + [rx_bits sync f_err pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation); + [sig_est noise_est] = snr_update(sig_est, noise_est, pd); + snr_est = calc_snr(sig_est, noise_est); + snr_est_log = [snr_est_log snr_est]; foff -= 0.5*f_err; prev_rx_symbols = rx_symbols; sync_log = [sync_log sync]; @@ -198,6 +209,9 @@ function fdmdv_demod(rawfilename, nbits, pngname) axis([0 secs 0 1.5]); title('Test Frame Sync') - - + figure(5) + clf; + plot(xt, snr_est_log); + title('SNR Estimates') + endfunction diff --git a/codec2-dev/octave/fdmdv_demod_c.m b/codec2-dev/octave/fdmdv_demod_c.m index e83cf392..4f1f1238 100644 --- a/codec2-dev/octave/fdmdv_demod_c.m +++ b/codec2-dev/octave/fdmdv_demod_c.m @@ -120,5 +120,9 @@ function fdmdv_demod_c(dumpfilename, bits) axis([0 secs 0 1.5]); title('Test Frame Sync') + figure(5) + clf; + plot(xt, snr_est_log_c(1:frames)); + title('SNR Estimates') endfunction diff --git a/codec2-dev/octave/fdmdv_ut.m b/codec2-dev/octave/fdmdv_ut.m index 83b629ed..a78eedfe 100644 --- a/codec2-dev/octave/fdmdv_ut.m +++ b/codec2-dev/octave/fdmdv_ut.m @@ -12,7 +12,7 @@ fdmdv; % load modem code % Simulation Parameters -------------------------------------- -frames = 100; +frames = 25; EbNo_dB = 7.3; Foff_hz = 0; modulation = 'dqpsk'; @@ -46,6 +46,11 @@ sync_log = []; test_frame_sync_log = []; test_frame_sync_state = 0; +% SNR estimation states + +sig_est = zeros(Nc+1,1); +noise_est = zeros(Nc+1,1); + % fixed delay simuation Ndelay = M+20; @@ -91,6 +96,7 @@ fest_state = 0; track = 0; track_log = []; + % --------------------------------------------------------------------- % Main loop % --------------------------------------------------------------------- @@ -181,12 +187,13 @@ for f=1:frames %rx_phase_log = [rx_phase_log rx_phase]; %rx_symbols = rx_symbols*exp(j*rx_phase); + [rx_bits sync foff_fine pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation); if strcmp(modulation,'dqpsk') - rx_symbols_log = [rx_symbols_log rx_symbols.*conj(prev_rx_symbols)*exp(j*pi/4)]; + %rx_symbols_log = [rx_symbols_log rx_symbols.*conj(prev_rx_symbols)*exp(j*pi/4)]; + rx_symbols_log = [rx_symbols_log pd]; else rx_symbols_log = [rx_symbols_log rx_symbols]; endif - [rx_bits sync foff_fine] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation); foff -= 0.5*ferr; prev_rx_symbols = rx_symbols; sync_log = [sync_log sync]; @@ -196,6 +203,10 @@ for f=1:frames [track fest_state] = freq_state(sync, fest_state); track_log = [track_log track]; + % Update SNR est + + [sig_est noise_est] = snr_update(sig_est, noise_est, pd); + % count bit errors if we find a test frame % Allow 15 frames for filter memories to fill and time est to settle @@ -238,14 +249,23 @@ end ber = total_bit_errors / total_bits; -% Peak to Average Power Ratio from http://www.dsplog.com +% Peak to Average Power Ratio calcs from http://www.dsplog.com papr = max(tx_fdm_log.*conj(tx_fdm_log)) / mean(tx_fdm_log.*conj(tx_fdm_log)); papr_dB = 10*log10(papr); -printf("Eb/No (meas): %2.2f (%2.2f) dB\nbits........: %d\nerrors......: %d\nBER.........: %1.4f\nPAPR........: %1.2f dB\nSNR.........: %2.1f dB\n", - EbNo_dB, 10*log10(0.25*tx_pwr*Fs/(Rs*Nc*noise_pwr)), - total_bits, total_bit_errors, ber, papr_dB, SNR ); +% Note Eb/No set point is for Nc data carriers only, exclduing pilot. +% This is convenient for testing BER versus Eb/No. Measured Eb/No +% includes power of pilot. Similar for SNR, first number is SNR excluding +% pilot pwr for Eb/No set point, 2nd value is measured SNR which will be a little +% higher as pilot power is included. + +printf("Eb/No (meas): %2.2f (%2.2f) dB\n", EbNo_dB, 10*log10(0.25*tx_pwr*Fs/(Rs*Nc*noise_pwr))); +printf("bits........: %d\n", total_bits); +printf("errors......: %d\n", total_bit_errors); +printf("BER.........: %1.4f\n", ber); +printf("PAPR........: %1.2f dB\n", papr_dB); +printf("SNR...(meas): %2.2f (%2.2f) dB\n", SNR, calc_snr(sig_est, noise_est)); % --------------------------------------------------------------------- % Plots diff --git a/codec2-dev/octave/phase2.m b/codec2-dev/octave/phase2.m index fc9462b5..5c148f38 100644 --- a/codec2-dev/octave/phase2.m +++ b/codec2-dev/octave/phase2.m @@ -6,7 +6,7 @@ function phase2(samname, png) N = 16000; - f=45; + f=43; model = load("../src/hts1a_phase_model.txt"); phase = load("../src/hts1a_phase_phase.txt"); Wo = model(f,1); @@ -14,10 +14,14 @@ function phase2(samname, png) L = model(f,2); A = model(f,3:(L+2)); phi = phase(f,1:L); + phi = zeros(1,L); + phi(3) = -pi/2; + phi(4) = -pi/4; + phi(5) = pi/2; s = zeros(1,N); - for m=1:L/2 + for m=3:5 s_m = A(m)*cos(m*Wo*(0:(N-1)) + phi(m)); s = s + s_m; endfor @@ -26,6 +30,13 @@ function phase2(samname, png) clf; plot(s(1:250)); + figure(2); + clf; + subplot(211) + plot((1:L)*Wo*4000/pi, 20*log10(A),'+'); + subplot(212) + plot((1:L)*Wo*4000/pi, phi,'+'); + fs=fopen(samname,"wb"); fwrite(fs,s,"short"); fclose(fs); diff --git a/codec2-dev/octave/plamp.m b/codec2-dev/octave/plamp.m index b8c471d3..79683596 100644 --- a/codec2-dev/octave/plamp.m +++ b/codec2-dev/octave/plamp.m @@ -67,6 +67,7 @@ function plamp(samname, f) clf; % s = [ Sn(2*(f-2)-1,:) Sn(2*(f-2),:) ]; s = [ Sn(2*f-1,:) Sn(2*f,:) ]; + size(s) plot(s); axis([1 length(s) -20000 20000]); diff --git a/codec2-dev/octave/tfdmdv.m b/codec2-dev/octave/tfdmdv.m index d554f411..67f4ac02 100644 --- a/codec2-dev/octave/tfdmdv.m +++ b/codec2-dev/octave/tfdmdv.m @@ -25,6 +25,8 @@ fest_state = 0; channel = []; channel_count = 0; next_nin = M; +sig_est = zeros(Nc+1,1); +noise_est = zeros(Nc+1,1); % Octave outputs we want to collect for comparison to C version @@ -50,6 +52,8 @@ rx_bits_log = []; sync_bit_log = []; coarse_fine_log = []; nin_log = []; +sig_est_log = []; +noise_est_log = []; for f=1:frames @@ -128,7 +132,12 @@ for f=1:frames end nin_log = [nin_log nin]; - [rx_bits sync_bit foff_fine] = qpsk_to_bits(prev_rx_symbols, rx_symbols, 'dqpsk'); + [rx_bits sync_bit foff_fine pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, 'dqpsk'); + + [sig_est noise_est] = snr_update(sig_est, noise_est, pd); + sig_est_log = [sig_est_log sig_est]; + noise_est_log = [noise_est_log noise_est]; + prev_rx_symbols = rx_symbols; rx_bits_log = [rx_bits_log rx_bits]; foff_fine_log = [foff_fine_log foff_fine]; @@ -242,6 +251,10 @@ stem_sig_and_error(14, 212, sync_bit_log_c, sync_bit_log - sync_bit_log_c, 'Sync stem_sig_and_error(15, 211, rx_bits_log_c(st:en), rx_bits_log(st:en) - rx_bits_log_c(st:en), 'RX bits', [1 en-st -1.5 1.5]) stem_sig_and_error(15, 212, nin_log_c, nin_log - nin_log_c, 'nin') +c = 1; +plot_sig_and_error(16, 211, sig_est_log(c,:), sig_est_log(c,:) - sig_est_log_c(c,:), 'sig est for SNR' ) +plot_sig_and_error(16, 212, noise_est_log(c,:), noise_est_log(c,:) - noise_est_log_c(c,:), 'noise est for SNR' ) + % --------------------------------------------------------------------------------------- % AUTOMATED CHECKS ------------------------------------------ % --------------------------------------------------------------------------------------- @@ -287,5 +300,7 @@ check(rx_bits_log, rx_bits_log_c, 'rx bits'); check(sync_bit_log, sync_bit_log_c, 'sync bit'); check(coarse_fine_log, coarse_fine_log_c, 'coarse_fine'); check(nin_log, nin_log_c, 'nin'); +check(sig_est_log, sig_est_log_c, 'sig_est'); +check(noise_est_log, noise_est_log_c, 'noise_est'); printf("\npasses: %d fails: %d\n", passes, fails); diff --git a/codec2-dev/src/c2sim.c b/codec2-dev/src/c2sim.c index fccc088a..ca6d854a 100644 --- a/codec2-dev/src/c2sim.c +++ b/codec2-dev/src/c2sim.c @@ -113,6 +113,9 @@ int main(int argc, char *argv[]) int vector_quant_Wo_e = 0; int dump_pitch_e = 0; FILE *fjvm = NULL; + #ifdef DUMP + int dump; + #endif char* opt_string = "ho:"; struct option long_options[] = { diff --git a/codec2-dev/src/fdmdv.c b/codec2-dev/src/fdmdv.c index 3e8e28a2..4fe36e04 100644 --- a/codec2-dev/src/fdmdv.c +++ b/codec2-dev/src/fdmdv.c @@ -102,6 +102,11 @@ static COMP cadd(COMP a, COMP b) return res; } +static float cabsolute(COMP a) +{ + return sqrt(pow(a.real, 2.0) + pow(a.imag, 2.0)); +} + /*---------------------------------------------------------------------------*\ FUNCTION....: fdmdv_create @@ -210,6 +215,11 @@ struct FDMDV *fdmdv_create(void) f->fest_state = 0; f->coarse_fine = COARSE; + + for(c=0; csig_est[c] = 0.0; + f->noise_est[c] = 0.0; + } return f; } @@ -829,7 +839,7 @@ float rx_est_timing(COMP rx_symbols[], for(i=0; iphase_difference, fdmdv->prev_rx_symbols, rx_symbols); memcpy(fdmdv->prev_rx_symbols, rx_symbols, sizeof(COMP)*(NC+1)); + snr_update(fdmdv->sig_est, fdmdv->noise_est, fdmdv->phase_difference); /* freq offset estimation state machine */ @@ -1135,6 +1204,50 @@ void fdmdv_demod(struct FDMDV *fdmdv, int rx_bits[], int *sync_bit, float rx_fdm fdmdv->foff -= TRACK_COEFF*foff_fine; } +/*---------------------------------------------------------------------------*\ + + FUNCTION....: calc_snr() + AUTHOR......: David Rowe + DATE CREATED: 17 May 2012 + + Calculate current SNR estimate (3000Hz noise BW) + +\*---------------------------------------------------------------------------*/ + +float calc_snr(float sig_est[], float noise_est[]) +{ + float S, SdB; + float mean, N50, N50dB, N3000dB; + float snr_dB; + int c; + + S = 0.0; + for(c=0; csnr = 0.0; /* TODO - implement SNR estimation */ + fdmdv_stats->snr_est = calc_snr(fdmdv->sig_est, fdmdv->noise_est); fdmdv_stats->fest_coarse_fine = fdmdv->coarse_fine; fdmdv_stats->foff = fdmdv->foff; fdmdv_stats->rx_timing = fdmdv->rx_timing; @@ -1161,14 +1270,9 @@ void fdmdv_get_demod_stats(struct FDMDV *fdmdv, struct FDMDV_STATS *fdmdv_stats) assert((NC+1) == FDMDV_NSYM); - for(c=0; crx_symbols[c] = fdmdv->phase_difference[c]; } - - /* place pilots somewhere convenient on scatter diagram */ - - fdmdv_stats->rx_symbols[NC] = cmult(fdmdv->phase_difference[NC], pi_on_4); - } /*---------------------------------------------------------------------------*\ diff --git a/codec2-dev/src/fdmdv.h b/codec2-dev/src/fdmdv.h index 4c31855f..66b9e573 100644 --- a/codec2-dev/src/fdmdv.h +++ b/codec2-dev/src/fdmdv.h @@ -58,7 +58,7 @@ extern "C" { struct FDMDV; struct FDMDV_STATS { - float snr; /* estimated SNR of rx signal in dB */ + float snr_est; /* estimated SNR of rx signal in dB (3 kHz noise BW) */ COMP rx_symbols[FDMDV_NSYM]; /* latest received symbols, for scatter plot */ int fest_coarse_fine; /* freq est state, 0-coarse 1-fine */ float foff; /* estimated freq offset in Hz */ diff --git a/codec2-dev/src/fdmdv_demod.c b/codec2-dev/src/fdmdv_demod.c index 91cd7ccb..d8b82dd5 100644 --- a/codec2-dev/src/fdmdv_demod.c +++ b/codec2-dev/src/fdmdv_demod.c @@ -75,6 +75,7 @@ int main(int argc, char *argv[]) float foff_log[MAX_FRAMES]; int sync_bit_log[MAX_FRAMES]; int rx_bits_log[FDMDV_BITS_PER_FRAME*MAX_FRAMES]; + float snr_est_log[MAX_FRAMES]; if (argc < 3) { printf("usage: %s InputModemRawFile OutputBitFile [OctaveDumpFile]\n", argv[0]); @@ -132,7 +133,7 @@ int main(int argc, char *argv[]) coarse_fine_log[f] = stats.fest_coarse_fine; sync_bit_log[f] = sync_bit; memcpy(&rx_bits_log[FDMDV_BITS_PER_FRAME*f], rx_bits, sizeof(int)*FDMDV_BITS_PER_FRAME); - + snr_est_log[f] = stats.snr_est; f++; } else @@ -202,6 +203,7 @@ int main(int argc, char *argv[]) octave_save_int(foct, "coarse_fine_log_c", coarse_fine_log, 1, f); octave_save_int(foct, "rx_bits_log_c", rx_bits_log, 1, FDMDV_BITS_PER_FRAME*f); octave_save_int(foct, "sync_bit_log_c", sync_bit_log, 1, f); + octave_save_float(foct, "snr_est_log_c", snr_est_log, 1, f, MAX_FRAMES); fclose(foct); } } diff --git a/codec2-dev/src/fdmdv_internal.h b/codec2-dev/src/fdmdv_internal.h index 435244fd..a2647b2d 100644 --- a/codec2-dev/src/fdmdv_internal.h +++ b/codec2-dev/src/fdmdv_internal.h @@ -69,6 +69,8 @@ #define FINE 1 #define TRACK_COEFF 0.5 +#define SNR_COEFF 0.9 /* SNR est averaging filter coeff */ + /*---------------------------------------------------------------------------*\ STRUCT for States @@ -124,6 +126,11 @@ struct FDMDV { int fest_state; int coarse_fine; + + /* SNR estimation states */ + + float sig_est[NC+1]; + float noise_est[NC+1]; }; /*---------------------------------------------------------------------------*\ @@ -150,6 +157,8 @@ float rx_est_timing(COMP rx_symbols[], COMP rx_baseband_mem_timing[NC+1][NFILTERTIMING], int nin); float qpsk_to_bits(int rx_bits[], int *sync_bit, COMP phase_difference[], COMP prev_rx_symbols[], COMP rx_symbols[]); +void snr_update(float sig_est[], float noise_est[], COMP phase_difference[]); int freq_state(int sync_bit, int *state); +float calc_snr(float sig_est[], float noise_est[]); #endif diff --git a/codec2-dev/unittest/tfdmdv.c b/codec2-dev/unittest/tfdmdv.c index 593b8139..b33a6342 100644 --- a/codec2-dev/unittest/tfdmdv.c +++ b/codec2-dev/unittest/tfdmdv.c @@ -84,6 +84,8 @@ int main(int argc, char *argv[]) float env_log[NT*P*FRAMES]; float rx_timing_log[FRAMES]; COMP rx_symbols_log[NC+1][FRAMES]; + float sig_est_log[NC+1][FRAMES]; + float noise_est_log[NC+1][FRAMES]; int rx_bits_log[FDMDV_BITS_PER_FRAME*FRAMES]; float foff_fine_log[FRAMES]; int sync_bit_log[FRAMES]; @@ -160,6 +162,7 @@ int main(int argc, char *argv[]) rx_filter(rx_filt, rx_baseband, fdmdv->rx_filter_memory, nin); rx_timing = rx_est_timing(rx_symbols, rx_filt, rx_baseband, fdmdv->rx_filter_mem_timing, env, fdmdv->rx_baseband_mem_timing, nin); foff_fine = qpsk_to_bits(rx_bits, &sync_bit, fdmdv->phase_difference, fdmdv->prev_rx_symbols, rx_symbols); + snr_update(fdmdv->sig_est, fdmdv->noise_est, fdmdv->phase_difference); memcpy(fdmdv->prev_rx_symbols, rx_symbols, sizeof(COMP)*(NC+1)); next_nin = M; @@ -222,6 +225,10 @@ int main(int argc, char *argv[]) /* qpsk_to_bits() */ memcpy(&rx_bits_log[FDMDV_BITS_PER_FRAME*f], rx_bits, sizeof(int)*FDMDV_BITS_PER_FRAME); + for(c=0; csig_est[c]; + noise_est_log[c][f] = fdmdv->noise_est[c]; + } foff_fine_log[f] = foff_fine; sync_bit_log[f] = sync_bit; @@ -255,6 +262,8 @@ int main(int argc, char *argv[]) octave_save_float(fout, "env_log_c", env_log, 1, NT*P*FRAMES, NT*P*FRAMES); octave_save_float(fout, "rx_timing_log_c", rx_timing_log, 1, FRAMES, FRAMES); octave_save_complex(fout, "rx_symbols_log_c", (COMP*)rx_symbols_log, (NC+1), FRAMES, FRAMES); + octave_save_float(fout, "sig_est_log_c", (float*)sig_est_log, (NC+1), FRAMES, FRAMES); + octave_save_float(fout, "noise_est_log_c", (float*)noise_est_log, (NC+1), FRAMES, FRAMES); octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, FDMDV_BITS_PER_FRAME*FRAMES); octave_save_float(fout, "foff_fine_log_c", foff_fine_log, 1, FRAMES, FRAMES); octave_save_int(fout, "sync_bit_log_c", sync_bit_log, 1, FRAMES); -- 2.25.1