diff options
Diffstat (limited to 'octave/fsk_llr_test.m')
| -rw-r--r-- | octave/fsk_llr_test.m | 294 |
1 files changed, 0 insertions, 294 deletions
diff --git a/octave/fsk_llr_test.m b/octave/fsk_llr_test.m deleted file mode 100644 index 3c21c64..0000000 --- a/octave/fsk_llr_test.m +++ /dev/null @@ -1,294 +0,0 @@ -% fsk_llr_test.m -% -% 2/4FSK simulation to develop LLR estimation algorithms for 4FSK/LDPC modems -% Modified version of David's fsk_llr.m; Bill - -#{ - TODO - The 'v' param of the Ricean pdf is the signal-only amplitude: genie value=16 - In practice, given varying input levels, this value needs to be estimated. - - A small scaling factor seems to improve 2FSK performance -- probably the 'sig' - estimate can be improved. - - Only tested with short code -- try a longer one! - - Simulation should be updated to exit Eb after given Nerr reached - -#} - -ldpc; - -% define Rician pdf -function y = rice(x,v,s) - s2 = s*s; - y = (x / s2) .* exp(-0.5 * (x.^2 + v.^2)/s2) .* besseli(0, x*v/s2); -endfunction - -function plot_pdf(v,s) - x=(0:0.1:2*v); - y= rice(x, v, s); - figure(201); hold on - plot(x,y,'g'); - %title('Rician pdf: signal carrier') - y= rice(x, 0, s); - plot(x,y,'b'); - title('Rician pdf: signal and noise-only carriers') - pause(0.01); -endfunction - -% single Eb/No point simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -function [raw_ber rx_filt rx_bits tx_symbols demapper sig_est ] = run_single(tx_bits, M, EcNodB, plt=0) - % Ec/N0 is per channel bit - bps = log2(M); % bits per symbol - Ts = 16; % length of each symbol in samples - - if length(tx_bits)==1 - Nbits = tx_bits; - tx_bits = randi(2,1,Nbits)-1; % make random bits - endif - - Nbits = length(tx_bits); - Nsymbols = Nbits/log2(M); - tx_symbols = zeros(1,Nsymbols); - - mapper = bps:-1:1; - % look up table demapper from symbols to bits (hard decision) - demapper=zeros(M,bps); - for m=1:M - for b=1:bps - if bitand(m-1,b) demapper(m,bps-b+1) = 1; end - end - end - - % continuous phase mFSK modulator - - w(1:M) = 2*pi*(1:M)/Ts; - tx_phase = 0; - tx = zeros(1,Ts*Nsymbols); - - for s=1:Nsymbols - bits_for_this_symbol = tx_bits(bps*(s-1)+1:bps*s); - symbol_index = bits_for_this_symbol * mapper' + 1; - tx_symbols(s) = symbol_index; - assert(demapper(symbol_index,:) == bits_for_this_symbol); - for k=1:Ts - tx_phase += w(symbol_index); - tx((s-1)*Ts+k) = exp(j*tx_phase); - end - end - - % AWGN channel noise - - - EsNodB = EcNodB + 10*log10(bps) - EsNo = 10^(EsNodB/10); - variance = Ts/EsNo; - noise = sqrt(variance/2)*(randn(1,Nsymbols*Ts) + j*randn(1,Nsymbols*Ts)); - rx = tx + noise; - - if plt==2, % check the Spectrum - [psd,Fpsd] =pwelch(rx,128,0.5,128,Ts); - figure(110); plot(Fpsd,10*log10(psd)); - title('Rx Signal: PSD '); - xlabel('Freq/Rs'); - %figure(111);plot(unwrap(arg(tx))); - pause(0.01); - endif - - - % integrate and dump demodulator - - rx_bits = zeros(1,Nbits); - rx_filt = zeros(Nsymbols,M); - rx_pows = zeros(1,M); - rx_nse_pow = 0.0; rx_sig_pow =0.0; - for s=1:Nsymbols - arx_symb = rx((s-1)*Ts + (1:Ts)); - for m=1:M - r= sum(exp(-j*w(m)*(1:Ts)) .* arx_symb); - rx_pows(m)= r * conj(r); - rx_filt(s,m) = abs(r); - end - [tmp symbol_index] = max(rx_filt(s,:)); - rx_sig_pow = rx_sig_pow + rx_pows(symbol_index); - rx_pows(symbol_index)=[]; - rx_nse_pow = rx_nse_pow + sum(rx_pows)/(M-1); - rx_bits(bps*(s-1)+1:bps*s) = demapper(symbol_index,:); - end - % using Rxpower = v^2 + sigmal^2 - - rx_sig_pow = rx_sig_pow/Nsymbols; - rx_nse_pow = rx_nse_pow/Nsymbols; - sig_est = sqrt(rx_nse_pow/2) % for Rayleigh: 2nd raw moment = 2 .sigma^2 - Kest = rx_sig_pow/(2.0*sig_est^2) -1.0 - - Nerrors = sum(xor(tx_bits, rx_bits)); - raw_ber = Nerrors/Nbits; - printf("EcNodB: %4.1f M: %2d Uncoded Nbits: %5d Nerrors: %4d (Raw) BER: %1.3f\n", ... - EcNodB, M, Nbits, Nerrors, raw_ber); - if plt==1, plot_hist(rx_filt,tx_symbols, M); end - -endfunction - - -% Plot histograms of Rx filter outputs -function plot_hist(rx_filt,tx_symbols, M) - % more general version of previous fn; - plots histograms for any Tx patterns - Smax = 36; - X = 0:Smax-1; - H = zeros(1,Smax); H2 = zeros(1,Smax); s2=0.0; - for m = 1:M - ind = tx_symbols==m; - ind2 = tx_symbols~=m; - H= H+ hist(rx_filt(ind,m),X); - H2= H2+ hist(rx_filt(ind2,m),X); - x=rx_filt(ind2,m); - s2 =s2 + sum(x(:).^2)/length(x); - end - disp('noise RMS is '); sqrt(s2/4) - figure(1); clf; plot(X,H); - title([num2str(M) 'FSK pdf for rx=tx symbol']) - figure(2); clf; plot(X,H2); - title([num2str(M) 'FSK pdf for rx!=tx symbol']) - pause(0.1); - -endfunction - -% 2FSK SD -> LLR mapping that we used for Wenet SSTV system -function llr = sd_to_llr(sd, HD=0) % original 2FSK + HD option - sd = sd / mean(abs(sd)); - x = sd - sign(sd); - sumsq = sum(x.^2); - summ = sum(x); - mn = summ/length(sd); - estvar = sumsq/length(sd) - mn*mn; - estEsN0 = 1/(2* estvar + 1E-3); - if HD==0, - llr = 4 * estEsN0 * sd; - else - llr = 4 * estEsN0 * sign(sd); - endif -endfunction - - -% single point LDPC encoded frame simulation, using 2FSK as a tractable starting point -% Note: ~/cml/matCreateConstellation.m has some support for FSK - can it do 4FSK? - -%%%%%%%%%%%%%%%%%%%%%%%%% - function [Nerrors raw_ber EcNodB] = run_single_ldpc(M, Ltype, Nbits,EbNodB, plt=0) - - disp([num2str(M) 'FSK coded test ... ']) - if M==2 - bps = 1; modulation = 'FSK'; mod_order=2; mapping = 'gray'; - elseif M==4 - bps = 2; modulation = 'FSK'; mod_order=4; mapping = 'gray'; - else - error('sorry - bad value of M!'); - endif - decoder_type = 0; max_iterations = 100; - - load H_256_768_22.txt - Krate = 1/3; - EcNodB = EbNodB + 10*log10(Krate); - code_param = ldpc_init_user(H_256_768_22, modulation, mod_order, mapping); - Nframes = floor(Nbits/code_param.data_bits_per_frame) - Nbits = Nframes*code_param.data_bits_per_frame - - % Encoder - data_bits = round(rand(1,code_param.data_bits_per_frame)); - tx_bits = []; - for f=1:Nframes; - codeword_bits = LdpcEncode(data_bits, code_param.H_rows, code_param.P_matrix); - tx_bits = [tx_bits codeword_bits]; - end - %tx_bits = zeros(1,length(tx_bits)); - - % modem/channel simulation - [raw_ber rx_filt rx_bits tx_symbols demapper sig_est ] = run_single(tx_bits,M,EcNodB, 0 ); - - % Decoder - Nerrors = 0; - for f=1:Nframes - st = (f-1)*code_param.coded_bits_per_frame/bps + 1; - en = st + code_param.coded_bits_per_frame/bps - 1; - - if or(Ltype==1, Ltype==3) - if bps==1, - sd = rx_filt(st:en,1) - rx_filt(st:en,2); - % OR ind = rx_filt(st:en,1) > rx_filt(st:en,2); - % llr = ind'*2 -1; % this works but use SNR scaling - if Ltype==3, HD=1; else, HD = 0; endif - llr = sd_to_llr(sd, HD)'; - endif - if bps==2, - if Ltype==3, - llr = mfsk_hd_to_llrs(rx_filt(st:en,:), demapper); - else - error('Ltype =1 not provided for coded 4FSK'); - endif - endif - endif - if Ltype==2, % SDs are converted to LLRs - v=16; - if plt==1, plot_pdf(v, sig_est); endif - llr = mfsk_sd_to_llrs(rx_filt(st:en,:), demapper, v, sig_est); - endif - - [x_hat, PCcnt] = MpDecode(llr, code_param.H_rows, code_param.H_cols, ... - max_iterations, decoder_type, 1, 1); - Niters = sum(PCcnt!=0); - detected_data = x_hat(Niters,:); - Nerrors += sum(xor(data_bits, detected_data(1:code_param.data_bits_per_frame))); - endfor - ber = Nerrors/Nbits; - printf("EbNodB: %4.1f Coded Nbits: %5d Nerrors: %4d BER: %1.3f\n", EbNodB, Nbits, Nerrors, ber); -endfunction - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%rand('seed',1); -%randn('seed',1); -format short -more off -init_cml(); - -% store results in array "res" and plot afterwards -% comment the following line if you want to retain prev sims -nrun = 0; clear res; - -Nbits = 20000; plt=0; - -#{ -disp(' uncoded runs') -for M= [2 4] -for Eb = [6:10] - raw_ber = run_single(Nbits, M, Eb, plt) % 2fsk coded - nrun = nrun+1; res(nrun,:) = [Eb Eb M -1 Nbits -1 raw_ber] -endfor -endfor -#} - -disp(' coded runs '); - -M=2, -for Ltype = [1 2 3] -for Eb = [7: 0.5: 9] - [Nerr raw_ber Ec] = run_single_ldpc(M, Ltype, Nbits, Eb, plt) - nrun = nrun+1; res(nrun,:) = [Eb Ec M Ltype Nbits Nerr raw_ber] -endfor -endfor - -M=4, %v=16; -for Ltype = [2 3] -for Eb = [8.0 8.3 8.6 ] - [Nerr raw_ber Ec] = run_single_ldpc(M, Ltype, Nbits, Eb, plt) - nrun = nrun+1; res(nrun,:) = [Eb Ec M Ltype Nbits Nerr raw_ber] -endfor -endfor - - -date = datestr(now) -save 'mfsk_test_res.mat' res date - |
