From d402eaf49458c274155e07ab150b585300539ab3 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 24 Sep 2015 21:11:42 +0000 Subject: [PATCH] refactored a little and wrote Octave function to generate files of modulated bits git-svn-id: https://svn.code.sf.net/p/freetel/code@2379 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/tqpsk.m | 148 +++++++++++++++++++++++++++----------- 1 file changed, 106 insertions(+), 42 deletions(-) diff --git a/codec2-dev/octave/tqpsk.m b/codec2-dev/octave/tqpsk.m index 4ec8765a..f6557c91 100644 --- a/codec2-dev/octave/tqpsk.m +++ b/codec2-dev/octave/tqpsk.m @@ -2,7 +2,16 @@ % % David Rowe Sep 2015 % -% QPSK modem Octave test sctipt +% QPSK modem Octave test scripts + +% TODO: +% correct freq offset +% output tx frame to a file of bits for 3rd party modulator +% improve phase est impl loss using longer window +% separate into mod and demod functions +% generate filter coeffs, save to C header file +% fine timing estimator and meas IL +% coarse timing (frame sync) % make sure we get same random numbers every time @@ -10,16 +19,8 @@ more off; qpsk; ldpc; -function sim_out = run_simulation(sim_in) - Ntrials = sim_in.Ntrials; - EsNodBvec = sim_in.EsNodBvec; - verbose = sim_in.verbose; - phase_offset = sim_in.phase_offset; - phase_est_en = sim_in.phase_est_en; - verbose = sim_in.verbose; - rand('state',1); - randn('state',1); +function [aqpsk code_param] = init_modem_ldpc % Init modem ------------------------------------------------------------------------------ @@ -45,9 +46,6 @@ function sim_out = run_simulation(sim_in) aqpsk.Np = 2; % number of pilots used for phase estimation aqpsk.rx_pilot_buf = zeros(1,aqpsk.Np); - Nsymb = aqpsk.Nsymb; - Nsymbpilot = aqpsk.Nsymbpilot; - % Init LDPC -------------------------------------------------------------------------- currentdir = pwd; @@ -66,6 +64,27 @@ function sim_out = run_simulation(sim_in) code_param = ldpc_init(aqpsk.code_rate, aqpsk.framesize, modulation, mod_order, mapping); assert(code_param.data_bits_per_frame == aqpsk.Ndatabits); +endfunction + + +function sim_out = run_simulation(sim_in) + Ntrials = sim_in.Ntrials; + EsNodBvec = sim_in.EsNodBvec; + verbose = sim_in.verbose; + phase_offset = sim_in.phase_offset; + phase_est_en = sim_in.phase_est_en; + verbose = sim_in.verbose; + + rand('state',1); + randn('state',1); + + % Init modem and LPDC ---------------------------------------------------------------- + + [aqpsk code_param] = init_modem_ldpc; + + Nsymb = aqpsk.Nsymb; + Nsymbpilot = aqpsk.Nsymbpilot; + % Start simulation ------------------------------------------------------------------- for ne = 1:length(EsNodBvec) @@ -135,32 +154,77 @@ end % ---------------------------------------------------------------------- -sim_in.phase_est_en = 1; -sim_in.phase_offset = 0; -sim_in.verbose = 1; -sim_in.EsNodBvec = -2:10; -sim_in.Ntrials = 10; - -sim_out = run_simulation(sim_in); - -EbNodB = sim_in.EsNodBvec - 10*log10(2); % QPSK has two bits/symbol -uncoded_BER_theory = 0.5*erfc(sqrt(10.^(EbNodB/10))); - -figure(1) -clf -semilogy(EbNodB, uncoded_BER_theory,'r;uncoded QPSK theory;') -hold on; -semilogy(EbNodB, sim_out.BER_uc,'r+;uncoded QPSK simulated;') -semilogy(EbNodB-10*log10(sim_out.code_rate), sim_out.BER+1E-10,'g;LDPC coded QPSK simulated;'); -hold off; -grid('minor') -xlabel('Eb/No (dB)') -ylabel('BER') -axis([min(EbNodB) max(EbNodB) min(uncoded_BER_theory) 1]) - -% correct freq offset -% output "demodulated" tx frame to a file of bits for 3rd party modulator -% actually estimate Es/No for LDPC -% improve phase est impl loss -% separate into enc and demod functions -% generate filter coeffs, save to C header file + +function symbol_rate_curves + sim_in.phase_est_en = 1; + sim_in.phase_offset = 0; + sim_in.verbose = 1; + sim_in.EsNodBvec = -2:10; + sim_in.Ntrials = 10; + + sim_out = run_simulation(sim_in); + + EbNodB = sim_in.EsNodBvec - 10*log10(2); % QPSK has two bits/symbol + uncoded_BER_theory = 0.5*erfc(sqrt(10.^(EbNodB/10))); + + figure(1) + clf + semilogy(EbNodB, uncoded_BER_theory,'r;uncoded QPSK theory;') + hold on; + semilogy(EbNodB, sim_out.BER_uc,'r+;uncoded QPSK simulated;') + semilogy(EbNodB-10*log10(sim_out.code_rate), sim_out.BER+1E-10,'g;LDPC coded QPSK simulated;'); + hold off; + grid('minor') + xlabel('Eb/No (dB)') + ylabel('BER') + axis([min(EbNodB) max(EbNodB) min(uncoded_BER_theory) 1]) + +endfunction + + +% We are using a 3rd party modulator, this function generates bits +% that can be passed to it. It's organised as a file of 8 bit bytes +% MSB is sent first. Each pair of bits is mapped to phases as: +% +% MSB LSB Phase +% 0 0 0 +% 0 1 90 +% 1 1 180 +% 1 0 270 + +function generate_modulator_input_file(filename, seconds) + + [aqpsk code_param] = init_modem_ldpc; + + Nframes = floor(seconds/aqpsk.Rf); + Nsecs = Nframes*aqpsk.Rf; + Nbitsframe = aqpsk.Nsymbpilot*aqpsk.bits_per_symb; + Nbytesframe = Nbitsframe/8; + + printf("Frames: %d Seconds: %3.1f QPSK Symb Rate: %5.2f\n", Nframes, Nsecs, aqpsk.Rs); + printf("Bit/frame: %d Packed Bytes/frame: %4.1f\n", Nbitsframe, Nbytesframe); + + fbit = fopen(filename,"wb"); + + for nn = 1:Nframes + tx_bits = round(rand(1, aqpsk.Ndatabits)); + [tx_codeword, tx_coded_symb] = ldpc_enc(tx_bits, code_param); + symbpilot_tx = insert_pilots(tx_coded_symb, aqpsk.pilots, aqpsk.Npilotstep); + + % demodulate QPSK symbols back to bits + + tx_frame = zeros(1, aqpsk.Nsymbpilot*aqpsk.bits_per_symb); + for s=1:aqpsk.Nsymbpilot + tx_frame(2*(s-1)+1:2*s) = qpsk_demod(symbpilot_tx(s)); + end + packed_tx_frame = packmsb(tx_frame); + fwrite(fbit, packed_tx_frame, "uchar"); + end + + fclose(fbit); + +endfunction + +% --------------------------------------------------------------------------------- + +generate_modulator_input_file("modinputbits_v0.1.bin", 300) -- 2.25.1