From: drowe67 Date: Thu, 2 Apr 2015 06:25:41 +0000 (+0000) Subject: C and Octave coherent psk modem code match, all tests passing yayyyyy X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=c4a79fd94401710cd3f3f3a12f7307b34fa8e2ac;p=freetel-svn-tracking.git C and Octave coherent psk modem code match, all tests passing yayyyyy git-svn-id: https://svn.code.sf.net/p/freetel/code@2101 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/octave/autotest.m b/codec2-dev/octave/autotest.m index 0a772e40..b6623d8a 100644 --- a/codec2-dev/octave/autotest.m +++ b/codec2-dev/octave/autotest.m @@ -53,13 +53,19 @@ function check(a, b, test_name, tol) end [m n] = size(a); + if m > n + ll = m; + else + ll = n; + end + printf("%s", test_name); for i=1:(25-length(test_name)) printf("."); end printf(": "); - e = sum(sum(abs(a - b))/n); + e = sum(sum(abs(a - b))/ll); if e < tol printf("OK\n"); passes++; diff --git a/codec2-dev/octave/cohpsk.m b/codec2-dev/octave/cohpsk.m index 2207f3b2..2cfa41ce 100644 --- a/codec2-dev/octave/cohpsk.m +++ b/codec2-dev/octave/cohpsk.m @@ -224,9 +224,11 @@ function [rx_symb rx_bits amp_ phi_ EsNo_ cohpsk] = qpsk_symbols_to_bits(cohpsk, for c=1:Nc for r=1:Nsymbrow i = (c-1)*Nsymbrow + r; - rx_symb(i) = ct_symb_buf(2+r,c)*exp(-j*phi_(c)); + rx_symb(r,c) = ct_symb_buf(2+r,c)*exp(-j*phi_(r,c)); + %rx_symb(r,c) = ct_symb_buf(2+r,c); rx_symb_linear(i) = rx_symb(i); rx_bits((2*(i-1)+1):(2*i)) = qpsk_demod(rx_symb(r,c)); + %printf("phi_ %d %d %f %f\n", r,c,real(exp(-j*phi_(r,c))), imag(exp(-j*phi_(r,c)))); end end @@ -483,11 +485,15 @@ function [next_sync cohpsk] = coarse_freq_offset_est(cohpsk, fdmdv, ch_fdm_frame sc = Ndft/Fs; bin_start = floor(f_start*sc+0.5)+1; bin_stop = floor(f_stop*sc+0.5)+1; + + %printf("f_start: %f f_stop: %f sc: %f bin_start: %d bin_stop: %d\n", f_start, f_stop, sc, bin_start, bin_stop); + x = bin_start-1:bin_stop-1; bin_est = x*T(bin_start:bin_stop)'/sum(T(bin_start:bin_stop)); - cohpsk.f_est = bin_est/sc; - printf("bin_est: %f coarse freq est: %f\n", bin_est, cohpsk.f_est); + cohpsk.f_est = floor(bin_est/sc+0.5); + printf("coarse freq est: %f\n", cohpsk.f_est); next_sync = 1; + end endfunction @@ -495,7 +501,7 @@ endfunction % returns index of start of frame and fine freq offset -function [next_sync cohpsk] = frame_sync_fine_timing_est(cohpsk, ch_symb, sync, next_sync) +function [next_sync cohpsk] = frame_sync_fine_freq_est(cohpsk, ch_symb, sync, next_sync) ct_symb_buf = cohpsk.ct_symb_buf; Nct_sym_buf = cohpsk.Nct_sym_buf; Rs = cohpsk.Rs; @@ -552,7 +558,7 @@ function [next_sync cohpsk] = frame_sync_fine_timing_est(cohpsk, ch_symb, sync, next_sync = 4; else next_sync = 0; - printf(" back to coarse freq offset ets...\n"); + printf(" back to coarse freq offset est...\n"); end end endfunction @@ -571,8 +577,8 @@ function acohpsk = fine_freq_correct(acohpsk, sync, next_sync); if (next_sync == 4) || (sync == 4) - if next_sync == 4 - + if (next_sync == 4) && (sync == 2) + % first frame, we've just gotten sync so fine freq correct all Nsymbrowpilot+2 samples ct_symb_ff_buf = acohpsk.ct_symb_buf(acohpsk.ct+1:acohpsk.ct+acohpsk.Nsymbrowpilot+2,:); @@ -582,14 +588,14 @@ function acohpsk = fine_freq_correct(acohpsk, sync, next_sync); end else - + % second and subsequent frames, just fine freq correct the latest Nsymbrowpilot - ct_symb_ff_buf(1:2,:) = ct_symb_ff_buf(Nsymbrowpilot+1:Nsymbrowpilot+2,:); - ct_symb_ff_buf(3:Nsymbrowpilot+2,:) = acohpsk.ct_symb_buf(acohpsk.ct+3:acohpsk.ct+acohpsk.Nsymbrowpilot+2,:); + ct_symb_ff_buf(1:2,:) = ct_symb_ff_buf(acohpsk.Nsymbrowpilot+1:acohpsk.Nsymbrowpilot+2,:); + ct_symb_ff_buf(3:acohpsk.Nsymbrowpilot+2,:) = acohpsk.ct_symb_buf(acohpsk.ct+3:acohpsk.ct+acohpsk.Nsymbrowpilot+2,:); for r=3:acohpsk.Nsymbrowpilot+2 - afdmdv.ff_phase *= afdmdv.ff_rect'; - ct_symb_ff_buf(r,:) *= afdmdv.ff_phase; + acohpsk.ff_phase *= acohpsk.ff_rect'; + ct_symb_ff_buf(r,:) *= acohpsk.ff_phase; end end diff --git a/codec2-dev/octave/tcohpsk.m b/codec2-dev/octave/tcohpsk.m index f2f497ca..f55113ab 100644 --- a/codec2-dev/octave/tcohpsk.m +++ b/codec2-dev/octave/tcohpsk.m @@ -104,11 +104,13 @@ rx_phi_log = []; ch_symb_log = []; rx_symb_log = []; rx_bits_log = []; +tx_bits_prev_log = []; noise_log = []; nerr_log = []; tx_baseband_log = []; tx_fdm_frame_log = []; ch_fdm_frame_log = []; +rx_fdm_frame_bb_log = []; phase = 1; freq = exp(j*2*pi*foff/acohpsk.Rs); @@ -123,6 +125,7 @@ rx_baseband_log = []; rx_fdm_frame_log = []; f_err_log = []; f_err_fail = 0; +ct_symb_ff_log = []; phase_ch = 1; sync = 0; @@ -208,7 +211,7 @@ for i=1:frames end mag = abs(fbb_phase_rx); fbb_phase_rx /= mag; - rx_fdm_frame_bb_log = [rx_fdm_log rx_fdm_frame_bb]; + rx_fdm_frame_bb_log = [rx_fdm_frame_bb_log rx_fdm_frame_bb]; % sample rate demod processing @@ -232,13 +235,9 @@ for i=1:frames % coarse timing (frame sync) and initial fine freq est --------------------------------------------- - [next_sync acohpsk] = frame_sync_fine_timing_est(acohpsk, ch_symb, sync, next_sync); - - if (i==1000) - xx - end - + [next_sync acohpsk] = frame_sync_fine_freq_est(acohpsk, ch_symb, sync, next_sync); acohpsk = fine_freq_correct(acohpsk, sync, next_sync); + ct_symb_ff_log = [ct_symb_ff_log; acohpsk.ct_symb_ff_buf(1:acohpsk.Nsymbrowpilot,:)]; if (sync == 4) || (next_sync == 4) [rx_symb rx_bits amp_ phi_ EsNo_] = qpsk_symbols_to_bits(acohpsk, acohpsk.ct_symb_ff_buf); @@ -246,17 +245,17 @@ for i=1:frames rx_amp_log = [rx_amp_log; amp_]; rx_phi_log = [rx_phi_log; phi_]; rx_bits_log = [rx_bits_log rx_bits]; + tx_bits_prev_log = [tx_bits_prev_log prev_tx_bits2]; % BER stats - if i > 2 - error_positions = xor(prev_tx_bits2, rx_bits); - Nerrs += sum(error_positions); - nerr_log = [nerr_log sum(error_positions)]; - Tbits += length(error_positions); - end + error_positions = xor(prev_tx_bits2, rx_bits); + Nerrs += sum(error_positions); + nerr_log = [nerr_log sum(error_positions)]; + Tbits += length(error_positions); end + %printf("f: %d sync: %d next_sync: %d\n", i, sync, next_sync); sync = sync_state_machine(sync, next_sync); prev_tx_bits2 = prev_tx_bits; @@ -272,43 +271,42 @@ stem_sig_and_error(3, 211, real(tx_fdm_log_c(1:n)), real(tx_fdm_frame_log(1:n) - stem_sig_and_error(3, 212, imag(tx_fdm_log_c(1:n)), imag(tx_fdm_frame_log(1:n) - tx_fdm_frame_log_c(1:n)), 'tx fdm frame im', [1 n -10 10]) stem_sig_and_error(4, 211, real(ch_fdm_frame_log_c(1:n)), real(ch_fdm_frame_log(1:n) - ch_fdm_frame_log_c(1:n)), 'ch fdm frame re', [1 n -10 10]) stem_sig_and_error(4, 212, imag(ch_fdm_frame_log_c(1:n)), imag(ch_fdm_frame_log(1:n) - ch_fdm_frame_log_c(1:n)), 'ch fdm frame im', [1 n -10 10]) +stem_sig_and_error(5, 211, real(rx_fdm_frame_bb_log_c(1:n)), real(rx_fdm_frame_bb_log(1:n) - rx_fdm_frame_bb_log_c(1:n)), 'rx fdm frame bb re', [1 n -10 10]) +stem_sig_and_error(5, 212, imag(rx_fdm_frame_bb_log_c(1:n)), imag(rx_fdm_frame_bb_log(1:n) - rx_fdm_frame_bb_log_c(1:n)), 'rx fdm frame bb im', [1 n -10 10]) -if 0 -stem_sig_and_error(4, 211, real(ch_symb_log_c(1:n)), real(ch_symb_log(1:n) - ch_symb_log_c(1:n)), 'ch symb re', [1 n -2 2]) -stem_sig_and_error(4, 212, imag(ch_symb_log_c(1:n)), imag(ch_symb_log(1:n) - ch_symb_log_c(1:n)), 'ch symb im', [1 n -2 2]) -stem_sig_and_error(5, 211, rx_amp_log_c(1:n), rx_amp_log(1:n) - rx_amp_log_c(1:n), 'Amp Est', [1 n -1.5 1.5]) -stem_sig_and_error(5, 212, rx_phi_log_c(1:n), rx_phi_log(1:n) - rx_phi_log_c(1:n), 'Phase Est', [1 n -4 4]) -stem_sig_and_error(6, 211, real(rx_symb_log_c(1:n)), real(rx_symb_log(1:n) - rx_symb_log_c(1:n)), 'rx symb re', [1 n -1.5 1.5]) -stem_sig_and_error(6, 212, imag(rx_symb_log_c(1:n)), imag(rx_symb_log(1:n) - rx_symb_log_c(1:n)), 'rx symb im', [1 n -1.5 1.5]) -stem_sig_and_error(7, 111, rx_bits_log_c(1:n), rx_bits_log(1:n) - rx_bits_log_c(1:n), 'rx bits', [1 n -1.5 1.5]) -end +[n m] = size(ch_symb_log); +stem_sig_and_error(6, 211, real(ch_symb_log_c), real(ch_symb_log - ch_symb_log_c), 'ch symb re', [1 n -1.5 1.5]) +stem_sig_and_error(6, 212, imag(ch_symb_log_c), imag(ch_symb_log - ch_symb_log_c), 'ch symb im', [1 n -1.5 1.5]) +stem_sig_and_error(7, 211, real(ct_symb_ff_log_c), real(ct_symb_ff_log - ct_symb_ff_log_c), 'ct symb ff re', [1 n -1.5 1.5]) +stem_sig_and_error(7, 212, imag(ct_symb_ff_log_c), imag(ct_symb_ff_log - ct_symb_ff_log_c), 'ct symb ff im', [1 n -1.5 1.5]) + +stem_sig_and_error(8, 211, rx_amp_log_c, rx_amp_log - rx_amp_log_c, 'Amp Est', [1 n -1.5 1.5]) +stem_sig_and_error(8, 212, rx_phi_log_c, rx_phi_log - rx_phi_log_c, 'Phase Est', [1 n -4 4]) +stem_sig_and_error(9, 211, real(rx_symb_log_c), real(rx_symb_log - rx_symb_log_c), 'rx symb re', [1 n -1.5 1.5]) +stem_sig_and_error(9, 212, imag(rx_symb_log_c), imag(rx_symb_log - rx_symb_log_c), 'rx symb im', [1 n -1.5 1.5]) +stem_sig_and_error(10, 111, rx_bits_log_c, rx_bits_log - rx_bits_log_c, 'rx bits', [1 n -1.5 1.5]) check(tx_bits_log, tx_bits_log_c, 'tx_bits'); check(tx_symb_log, tx_symb_log_c, 'tx_symb'); check(tx_fdm_frame_log, tx_fdm_frame_log_c, 'tx_fdm_frame'); check(ch_fdm_frame_log, ch_fdm_frame_log_c, 'ch_fdm_frame'); - -if 0 - -check(rx_baseband_log, rx_baseband_log_c, 'rx_baseband',0.01); -check(rx_filt_log, rx_filt_log_c, 'rx_filt'); +check(rx_fdm_frame_bb_log, rx_fdm_frame_bb_log_c, 'rx_fdm_frame_bb', 0.01); check(ch_symb_log, ch_symb_log_c, 'ch_symb',0.01); +check(ct_symb_ff_log, ct_symb_ff_log_c, 'ct_symb_ff',0.01); check(rx_amp_log, rx_amp_log_c, 'rx_amp_log',0.01); -check(rx_phi_log, rx_phi_log_c, 'rx_phi_log'); +check(rx_phi_log, rx_phi_log_c, 'rx_phi_log',0.01); check(rx_symb_log, rx_symb_log_c, 'rx_symb',0.01); check(rx_bits_log, rx_bits_log_c, 'rx_bits'); -end % Determine bit error rate sz = length(tx_bits_log_c); -Nerrs_c = sum(xor(tx_bits_log_c(framesize+1:sz-2*framesize), rx_bits_log_c(3*framesize+1:sz))); -Tbits_c = sz - 2*framesize; +Nerrs_c = sum(xor(tx_bits_prev_log, rx_bits_log_c)); +Tbits_c = length(tx_bits_prev_log); ber_c = Nerrs_c/Tbits_c; ber = Nerrs/Tbits; printf("EsNodB: %4.1f ber..: %3.2f Nerrs..: %d Tbits..: %d\n", EsNodB, ber, Nerrs, Tbits); printf("EsNodB: %4.1f ber_c: %3.2f Nerrs_c: %d Tbits_c: %d\n", EsNodB, ber_c, Nerrs_c, Tbits_c); -printf("f_err std: %f fails: %d\n", std(f_err_log), f_err_fail); % C header file of noise samples so C version gives extacly the same results diff --git a/codec2-dev/src/codec2_cohpsk.h b/codec2-dev/src/codec2_cohpsk.h index 65de8299..60acc0dd 100644 --- a/codec2-dev/src/codec2_cohpsk.h +++ b/codec2-dev/src/codec2_cohpsk.h @@ -41,7 +41,8 @@ void cohpsk_destroy(struct COHPSK *coh); void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC], int tx_bits[], int nbits); void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][COHPSK_NC]); void coarse_freq_offset_est(struct COHPSK *coh, struct FDMDV *fdmdv, COMP ch_fdm_frame[], int sync, int *next_sync); -void frame_sync_fine_timing_est(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC], int sync, int *next_sync); -int sync_state_machine(sync, next_sync); +void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC], int sync, int *next_sync); +void fine_freq_correct(struct COHPSK *coh, int sync, int next_sync); +int sync_state_machine(int sync, int next_sync); #endif diff --git a/codec2-dev/src/cohpsk.c b/codec2-dev/src/cohpsk.c index 7818dc88..89ec8764 100644 --- a/codec2-dev/src/cohpsk.c +++ b/codec2-dev/src/cohpsk.c @@ -105,6 +105,8 @@ struct COHPSK *cohpsk_create(void) } } + coh->ff_phase.real = 1.0; coh->ff_phase.imag = 0.0; + return coh; } @@ -193,10 +195,10 @@ void bits_to_qpsk_symbols(COMP tx_symb[][PILOTS_NC], int tx_bits[], int nbits) void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][COHPSK_NC]) { - int r, c, i; - COMP corr, rot, pi_on_4; + int p, r, c, i; + COMP corr, rot, pi_on_4, phi_rect; float mag, phi_, amp_; - short sampling_points[] = {1, 2, 7, 8}; + short sampling_points[] = {0, 1, 6, 7}; pi_on_4.real = cosf(M_PI/4); pi_on_4.imag = sinf(M_PI/4); @@ -206,14 +208,14 @@ void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][ for(c=0; cpilot2[r][c], ct_symb_buf[sampling_points[r]][c])); - mag += cabsolute(ct_symb_buf[sampling_points[r]][c]); + for(p=0; ppilot2[p][c], ct_symb_buf[sampling_points[p]][c])); + mag += cabsolute(ct_symb_buf[sampling_points[p]][c]); } phi_ = atan2f(corr.imag, corr.real); - amp_ = mag/2*NPILOTSFRAME; - for(r=0; r<2*NPILOTSFRAME; r++) { + amp_ = mag/(NPILOTSFRAME+2); + for(r=0; rphi_[r][c] = phi_; coh->amp_[r][c] = amp_; } @@ -222,16 +224,19 @@ void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][ /* now correct phase of data symbols and make decn on bits */ for(c=0; cphi_[0][c]); rot.imag = -sinf(coh->phi_[0][c]); + phi_rect.real = cosf(coh->phi_[0][c]); phi_rect.imag = -sinf(coh->phi_[0][c]); + //rot.real = 1.0; rot.imag = 0.0; for (r=0; rrx_symb[r][c] = cmult(ct_symb_buf[NPILOTSFRAME + r][c], rot); + coh->rx_symb[r][c] = cmult(ct_symb_buf[NPILOTSFRAME + r][c], phi_rect); + //printf("%d %d %f %f\n", r,c, coh->rx_symb[r][c].real, coh->rx_symb[r][c].imag); + //printf("phi_ %d %d %f %f\n", r,c, ct_symb_buf[NPILOTSFRAME + r][c].real, ct_symb_buf[NPILOTSFRAME + r][c].imag); rot = cmult(coh->rx_symb[r][c], pi_on_4); rx_bits[2*i+1] = rot.real < 0; rx_bits[2*i] = rot.imag < 0; } } - + } @@ -260,13 +265,14 @@ void coarse_freq_offset_est(struct COHPSK *coh, struct FDMDV *fdmdv, COMP ch_fdm sc = (float)COARSE_FEST_NDFT/FS; bin_start = floorf(f_start*sc+0.5); bin_stop = floorf(f_stop*sc+0.5); - // printf("f_start: %f f_stop: %f sc: %f bin_start: %d bin_stop: %d\n", - // f_start, f_stop, sc, bin_start, bin_stop); + //printf("f_start: %f f_stop: %f sc: %f bin_start: %d bin_stop: %d\n", + // f_start, f_stop, sc, bin_start, bin_stop); for(i=0; if_est = bin_est/sc; + coh->f_est = floor(bin_est/sc+0.5); - printf("bin_est: %f coarse freq est: %f\n", bin_est, coh->f_est); - + printf("coarse freq est: %f\n", coh->f_est); + *next_sync = 1; } } @@ -298,14 +304,16 @@ void coarse_freq_offset_est(struct COHPSK *coh, struct FDMDV *fdmdv, COMP ch_fdm AUTHOR......: David Rowe DATE CREATED: April 2015 - Returns an estimate of frequency offset, advances to next sync state. + Returns an estimate of frame sync (coarse timing) offset and fine + frequency offset, advances to next sync state if we have a reliable + match for frame sync. TODO: This is very stack heavy for an embedded uC. Tweak algorthim to use a smaller DFT and test. \*---------------------------------------------------------------------------*/ -void frame_sync_fine_timing_est(struct COHPSK *coh, COMP ch_symb[][PILOTS_NC], int sync, int *next_sync) +void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][PILOTS_NC], int sync, int *next_sync) { int sampling_points[] = {0, 1, 6, 7}; int r,c,i,p,t; @@ -339,14 +347,14 @@ void frame_sync_fine_timing_est(struct COHPSK *coh, COMP ch_symb[][PILOTS_NC], i corr.real = 0.0; corr.imag = 0.0; mag = 0.0; for (c=0; cct_symb_buf[t+sampling_points[p]][c]); corr = cadd(corr, fcmult(coh->pilot2[p][c], f_corr)); mag += cabsolute(f_corr); } } - //printf(" f: %f t: %d corr: %f %f\n", f_fine, t, real(corr), imag(corr)); + //printf(" f: %f t: %d corr: %f %f\n", f_fine, t, corr.real, corr.imag); if (cabsolute(corr) > max_corr) { max_corr = cabsolute(corr); max_mag = mag; @@ -357,8 +365,8 @@ void frame_sync_fine_timing_est(struct COHPSK *coh, COMP ch_symb[][PILOTS_NC], i } - coh->ff_rect.real = cosf(-coh->f_fine_est*2.0*M_PI/RS); - coh->ff_rect.imag = sinf(-coh->f_fine_est*2.0*M_PI/RS); + coh->ff_rect.real = cosf(coh->f_fine_est*2.0*M_PI/RS); + coh->ff_rect.imag = -sinf(coh->f_fine_est*2.0*M_PI/RS); printf(" fine freq f: %f max_corr: %f max_mag: %f ct: %d\n", coh->f_fine_est, max_corr, max_mag, coh->ct); if (max_corr/max_mag > 0.9) { @@ -367,18 +375,83 @@ void frame_sync_fine_timing_est(struct COHPSK *coh, COMP ch_symb[][PILOTS_NC], i } else { *next_sync = 0; - printf(" back to coarse freq offset ets...\n"); + printf(" back to coarse freq offset est...\n"); } - //exit(0); + } } -int sync_state_machine(sync, next_sync) +/*---------------------------------------------------------------------------*\ + + FUNCTION....: fine_freq_correct() + AUTHOR......: David Rowe + DATE CREATED: April 2015 + + Fine frequency correction of symbols at rate Rs. + +\*---------------------------------------------------------------------------*/ + +void fine_freq_correct(struct COHPSK *coh, int sync, int next_sync) { + int r,c; + float mag; + + /* + We can decode first frame that we achieve sync. Need to fine freq + correct all of it's symbols, including pilots. From then on, just + correct new symbols into frame. make copy, so if we lose sync we + havent fine freq corrected ct_symb_buf if next_sync == 4 correct + all 8 if sync == 2 correct latest 6. + */ + + if ((next_sync == 4) || (sync == 4)) { + + if ((next_sync == 4) && (sync == 2)) { + + /* first frame, we've just gotten sync so fine freq correct all Nsymbrowpilot+2 samples */ + + for(r=0; rff_phase = cmult(coh->ff_phase, cconj(coh->ff_rect)); + for(c=0; cct_symb_ff_buf[r][c] = coh->ct_symb_buf[coh->ct+r][c]; + coh->ct_symb_ff_buf[r][c] = cmult(coh->ct_symb_ff_buf[r][c], coh->ff_phase); + } + } + } + else { + + /* second and subsequent frames, just fine freq correct the latest Nsymbrowpilot */ + + for(r=0; r<2; r++) { + for(c=0; cct_symb_ff_buf[r][c] = coh->ct_symb_ff_buf[r+NSYMROWPILOT][c]; + } + } + + for(; rff_phase = cmult(coh->ff_phase, cconj(coh->ff_rect)); + for(c=0; cct_symb_ff_buf[r][c] = coh->ct_symb_buf[coh->ct+r][c]; + //printf("%d %d %f %f\n", r,c,coh->ct_symb_ff_buf[r][c].real, coh->ct_symb_ff_buf[r][c].imag); + coh->ct_symb_ff_buf[r][c] = cmult(coh->ct_symb_ff_buf[r][c], coh->ff_phase); + } + } + } + + mag = cabsolute(coh->ff_phase); + coh->ff_phase.real /= mag; + coh->ff_phase.imag /= mag; + } +} + + +int sync_state_machine(int sync, int next_sync) { if (sync == 1) next_sync = 2; sync = next_sync; + + return sync; } diff --git a/codec2-dev/src/cohpsk_internal.h b/codec2-dev/src/cohpsk_internal.h index d4b3175c..4f5a7222 100644 --- a/codec2-dev/src/cohpsk_internal.h +++ b/codec2-dev/src/cohpsk_internal.h @@ -41,9 +41,11 @@ struct COHPSK { kiss_fft_cfg fft_coarse_fest; float f_est; COMP ct_symb_buf[NCT_SYMB_BUF][PILOTS_NC]; + int ct; /* coarse timing offset in symbols */ float f_fine_est; - int ct; COMP ff_rect; + COMP ff_phase; + COMP ct_symb_ff_buf[NSYMROWPILOT+2][PILOTS_NC]; }; diff --git a/codec2-dev/unittest/tcohpsk.c b/codec2-dev/unittest/tcohpsk.c index 350e4306..b0916083 100644 --- a/codec2-dev/unittest/tcohpsk.c +++ b/codec2-dev/unittest/tcohpsk.c @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) COMP ch_fdm_frame_log[M*NSYMROWPILOT*FRAMES]; COMP rx_fdm_frame_bb_log[M*NSYMROWPILOT*FRAMES]; COMP ch_symb_log[NSYMROWPILOT*FRAMES][PILOTS_NC]; - + COMP ct_symb_ff_log[NSYMROWPILOT*FRAMES][PILOTS_NC]; float rx_amp_log[NSYMROW*FRAMES][PILOTS_NC]; float rx_phi_log[NSYMROW*FRAMES][PILOTS_NC]; COMP rx_symb_log[NSYMROW*FRAMES][PILOTS_NC]; @@ -94,13 +94,12 @@ int main(int argc, char *argv[]) int rx_baseband_log_col_index = 0; COMP rx_baseband_log[PILOTS_NC][(M+M/P)*NSYMROWPILOT*FRAMES]; - int ct; - int sync, next_sync; + int sync, next_sync, log_bits; coh = cohpsk_create(); assert(coh != NULL); - log_r = log_data_r = noise_r = 0; + log_r = log_data_r = noise_r = log_bits = 0; ptest_bits_coh = (int*)test_bits_coh; ptest_bits_coh_end = (int*)test_bits_coh + sizeof(test_bits_coh)/sizeof(int); @@ -196,14 +195,16 @@ int main(int argc, char *argv[]) /* coarse timing (frame sync) and initial fine freq est */ - frame_sync_fine_timing_est(coh, ch_symb, sync, &next_sync); - - /* Coherent phase estimation and correction */ - - qpsk_symbols_to_bits(coh, rx_bits, ct_symb_buf + ct); + frame_sync_fine_freq_est(coh, ch_symb, sync, &next_sync); + fine_freq_correct(coh, sync, next_sync); - sync = sync_state_machine(sync, next_sync); + if ((sync == 4) || (next_sync == 4)) { + qpsk_symbols_to_bits(coh, rx_bits, coh->ct_symb_ff_buf); + } + //printf("f: %d sync: %d next_sync: %d\n", f, sync, next_sync); + sync = sync_state_machine(sync, next_sync); + /* --------------------------------------------------------*\ Log each vector \*---------------------------------------------------------*/ @@ -217,24 +218,28 @@ int main(int argc, char *argv[]) for(c=0; cct_symb_ff_buf[r][c]; } } - for(r=0; ramp_[r][c]; - rx_phi_log[log_data_r][c] = coh->phi_[r][c]; - rx_symb_log[log_data_r][c] = coh->rx_symb[r][c]; + if ((sync == 4) || (next_sync == 4)) { + + for(r=0; ramp_[r][c]; + rx_phi_log[log_data_r][c] = coh->phi_[r][c]; + rx_symb_log[log_data_r][c] = coh->rx_symb[r][c]; + } } + memcpy(&rx_bits_log[COHPSK_BITS_PER_FRAME*log_bits], rx_bits, sizeof(int)*COHPSK_BITS_PER_FRAME); + log_bits++; } - memcpy(&rx_bits_log[COHPSK_BITS_PER_FRAME*f], rx_bits, sizeof(int)*COHPSK_BITS_PER_FRAME); assert(log_r <= NSYMROWPILOT*FRAMES); assert(noise_r <= NSYMROWPILOT*M*FRAMES); assert(log_data_r <= NSYMROW*FRAMES); } - /*---------------------------------------------------------*\ Dump logs to Octave file for evaluation by tcohpsk.m Octave script @@ -251,10 +256,11 @@ int main(int argc, char *argv[]) octave_save_complex(fout, "rx_baseband_log_c", (COMP*)rx_baseband_log, PILOTS_NC, rx_baseband_log_col_index, (M+M/P)*FRAMES*NSYMROWPILOT); octave_save_complex(fout, "rx_filt_log_c", (COMP*)rx_filt_log, PILOTS_NC, rx_filt_log_col_index, (P+1)*FRAMES*NSYMROWPILOT); octave_save_complex(fout, "ch_symb_log_c", (COMP*)ch_symb_log, NSYMROWPILOT*FRAMES, PILOTS_NC, PILOTS_NC); - octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, NSYMROW*FRAMES, PILOTS_NC, PILOTS_NC); - octave_save_float(fout, "rx_phi_log_c", (float*)rx_phi_log, NSYMROW*FRAMES, PILOTS_NC, PILOTS_NC); - octave_save_complex(fout, "rx_symb_log_c", (COMP*)rx_symb_log, NSYMROW*FRAMES, PILOTS_NC, PILOTS_NC); - octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, COHPSK_BITS_PER_FRAME*FRAMES); + octave_save_complex(fout, "ct_symb_ff_log_c", (COMP*)ct_symb_ff_log, NSYMROWPILOT*FRAMES, PILOTS_NC, PILOTS_NC); + octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, log_data_r, PILOTS_NC, PILOTS_NC); + octave_save_float(fout, "rx_phi_log_c", (float*)rx_phi_log, log_data_r, PILOTS_NC, PILOTS_NC); + octave_save_complex(fout, "rx_symb_log_c", (COMP*)rx_symb_log, log_data_r, PILOTS_NC, PILOTS_NC); + octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, COHPSK_BITS_PER_FRAME*log_bits); fclose(fout); fdmdv_destroy(fdmdv);