From: drowe67 Date: Tue, 26 May 2015 06:54:31 +0000 (+0000) Subject: cohpsk sample slip code interated into C and initial tests passing, need some better... X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=28a3350f12231f3fa8686021734eecc33ba9b0d6;p=freetel-svn-tracking.git cohpsk sample slip code interated into C and initial tests passing, need some better tests with C version of Fs offset simulation git-svn-id: https://svn.code.sf.net/p/freetel/code@2148 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/octave/tcohpsk.m b/codec2-dev/octave/tcohpsk.m index 71af0c22..caa83b9e 100644 --- a/codec2-dev/octave/tcohpsk.m +++ b/codec2-dev/octave/tcohpsk.m @@ -337,27 +337,14 @@ ch_fdm_frame_log = resample(ch_fdm_frame_log, (1E6 + sample_rate_ppm), 1E6); % Now run demod ---------------------------------------------------------------- ch_fdm_frame_log_index = 1; +nin = M; f = 0; +nin_frame = acohpsk.Nsymbrowpilot*M; %while (ch_fdm_frame_log_index + acohpsk.Nsymbrowpilot*M+M/P) < length(ch_fdm_frame_log) for f=1:frames; acohpsk.frame = f; - if sync == 0 - nin = M; - else - nin = M; - if 0 - if rx_timing(1) > M/P - nin = M + M/P; - end - if rx_timing(1) < -M/P - nin = M - M/P; - end - end - end - - nin_frame = (acohpsk.Nsymbrowpilot-1)*M + nin; ch_fdm_frame = ch_fdm_frame_log(ch_fdm_frame_log_index:ch_fdm_frame_log_index + nin_frame - 1); ch_fdm_frame_log_index += nin_frame; @@ -390,6 +377,7 @@ for f=1:frames; rx_filt_log = [rx_filt_log rx_filt]; ch_symb_log = [ch_symb_log; ch_symb]; + rx_timing_log = [rx_timing_log rx_timing]; for i=1:Nsw-1 acohpsk.ct_symb_buf = update_ct_symb_buf(acohpsk.ct_symb_buf, ch_symb((i-1)*acohpsk.Nsymbrowpilot+1:i*acohpsk.Nsymbrowpilot,:), acohpsk.Nct_sym_buf, acohpsk.Nsymbrowpilot); @@ -419,7 +407,8 @@ for f=1:frames; rx_baseband_log = [rx_baseband_log rx_baseband]; rx_filt_log = [rx_filt_log rx_filt]; ch_symb_log = [ch_symb_log; ch_symb]; - + rx_timing_log = [rx_timing_log rx_timing]; + for i=1:Nsw-1 acohpsk.ct_symb_buf = update_ct_symb_buf(acohpsk.ct_symb_buf, ch_symb((i-1)*acohpsk.Nsymbrowpilot+1:i*acohpsk.Nsymbrowpilot,:), acohpsk.Nct_sym_buf, acohpsk.Nsymbrowpilot); end @@ -492,6 +481,20 @@ for f=1:frames; [sync acohpsk] = sync_state_machine(acohpsk, sync, next_sync); + % work out how many samples we need for next time + + nin = M; + if sync == 1 + if rx_timing(length(rx_timing)) > M/P + nin = M + M/P; + end + if rx_timing(length(rx_timing)) < -M/P + nin = M - M/P; + end + end + nin_frame = (acohpsk.Nsymbrowpilot-1)*M + nin; + %printf("%f %d %d\n", rx_timing(length(rx_timing)), nin, nin_frame); + prev_tx_bits2 = prev_tx_bits; prev_tx_bits = tx_bits; @@ -545,6 +548,7 @@ if compare_with_c stem_sig_and_error(10, 111, rx_bits_log_c, rx_bits_log - rx_bits_log_c, 'rx bits', [1 length(rx_bits_log) -1.5 1.5]) stem_sig_and_error(11, 111, f_est_log_c - Fcentre, f_est_log - f_est_log_c, 'f est', [1 length(f_est_log) foff-5 foff+5]) + stem_sig_and_error(12, 111, rx_timing_log_c, rx_timing_log_c - rx_timing_log, 'rx timing', [1 length(rx_timing_log) -M M]) check(tx_bits_log, tx_bits_log_c, 'tx_bits'); check(tx_symb_log, tx_symb_log_c, 'tx_symb'); @@ -557,6 +561,7 @@ if compare_with_c check(rx_amp_log, rx_amp_log_c, 'rx_amp_log',0.01); check(phi_log_diff, zeros(length(phi_log_diff), Nc*Nd), 'rx_phi_log',0.05); check(rx_symb_log, rx_symb_log_c, 'rx_symb',0.01); + check(rx_timing_log, rx_timing_log_c, 'rx_timing',0.001); check(rx_bits_log, rx_bits_log_c, 'rx_bits'); check(f_est_log, f_est_log_c, 'f_est'); diff --git a/codec2-dev/src/codec2_cohpsk.h b/codec2-dev/src/codec2_cohpsk.h index 52e08c59..b4e227c5 100644 --- a/codec2-dev/src/codec2_cohpsk.h +++ b/codec2-dev/src/codec2_cohpsk.h @@ -32,7 +32,7 @@ #define COHPSK_NC 7 /* hard coded for now */ #define COHPSK_SAMPLES_PER_FRAME 600 #define COHPSK_RS 75 -#define COHPSK_FS 7500 +#define COHPSK_FS 7500 /* note this is a wierd value to get an integer oversampling rate */ #include "comp.h" #include "codec2_fdmdv.h" @@ -42,6 +42,6 @@ struct COHPSK; struct COHPSK *cohpsk_create(void); void cohpsk_destroy(struct COHPSK *coh); void cohpsk_mod(struct COHPSK *cohpsk, COMP tx_fdm[], int tx_bits[]); -void cohpsk_demod(struct COHPSK *cohpsk, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[]); +void cohpsk_demod(struct COHPSK *cohpsk, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin_frame); #endif diff --git a/codec2-dev/src/cohpsk.c b/codec2-dev/src/cohpsk.c index 31758618..5d04b4b4 100644 --- a/codec2-dev/src/cohpsk.c +++ b/codec2-dev/src/cohpsk.c @@ -118,6 +118,7 @@ struct COHPSK *cohpsk_create(void) coh->sync = 0; coh->frame = 0; coh->ratio = 0.0; + coh->nin = COHPSK_M; /* clear sync window buffer */ @@ -160,6 +161,8 @@ struct COHPSK *cohpsk_create(void) coh->rx_filt_log_col_index = 0; coh->ch_symb_log = NULL; coh->ch_symb_log_r = 0; + coh->rx_timing_log = NULL; + coh->rx_timing_log_index = 0; return coh; } @@ -751,7 +754,7 @@ void fdmdv_freq_shift_coh(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COMP ch_fdm_frame[], float *f_est, int nsymb, int nin, int freq_track) { struct FDMDV *fdmdv = coh->fdmdv; - int r, c, i; + int r, c, i, ch_fdm_frame_index; COMP rx_fdm_frame_bb[COHPSK_M]; COMP rx_baseband[COHPSK_NC*ND][COHPSK_M+COHPSK_M/P]; COMP rx_filt[COHPSK_NC*ND][P+1]; @@ -760,10 +763,11 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM float beta, g; COMP adiff, amod_strip, mod_strip; - assert(nin < COHPSK_M*NSYMROWPILOT); + ch_fdm_frame_index = 0; for (r=0; rfbb_phase_rx, nin); + fdmdv_freq_shift_coh(rx_fdm_frame_bb, &ch_fdm_frame[ch_fdm_frame_index], -(*f_est), &fdmdv->fbb_phase_rx, nin); + ch_fdm_frame_index += nin; fdm_downconvert_coh(rx_baseband, COHPSK_NC*ND, rx_fdm_frame_bb, fdmdv->phase_rx, fdmdv->freq, nin); rx_filter_coh(rx_filt, COHPSK_NC*ND, rx_baseband, coh->rx_filter_memory, nin); rx_timing = rx_est_timing(rx_onesym, fdmdv->Nc, rx_filt, fdmdv->rx_filter_mem_timing, env, nin, COHPSK_M); @@ -823,12 +827,12 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM } if (coh->rx_filt_log) { - for(c=0; crx_filt_log[c*coh->rx_filt_log_col_sz + coh->rx_filt_log_col_index + i] = rx_filt[c][i]; } } - coh->rx_filt_log_col_index += P; + coh->rx_filt_log_col_index += nin/(COHPSK_M/P); } if (coh->ch_symb_log) { @@ -837,8 +841,20 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM } coh->ch_symb_log_r++; } + + if (coh->rx_timing_log) { + coh->rx_timing_log[coh->rx_timing_log_index] = rx_timing; + coh->rx_timing_log_index++; + //printf("rx_timing_log_index: %d\n", coh->rx_timing_log_index); + } + + /* we only allow a timing shift on one symbol per frame */ + + if (nin != COHPSK_M) + nin = COHPSK_M; } + coh->rx_timing = rx_timing; } @@ -848,39 +864,31 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM AUTHOR......: David Rowe DATE CREATED: 5/4/2015 - COHPSK demodulator, takes an array of COHPSK_SAMPLES_PER_FRAME - modulated samples, returns an array of COHPSK_BITS_PER_FRAME bits. + COHPSK demodulator, takes an array of (nominally) nin_frame = + COHPSK_SAMPLES_PER_FRAME modulated samples, returns an array of + COHPSK_BITS_PER_FRAME bits. The input signal is complex to support single sided frequency shifting before the demod input (e.g. click to tune feature). - The number of input samples is fixed, and unlike the FDMDV modem - doesn't change to adjust for differences in transmit and receive - sample clocks. This means frame sync will occasionally be lost, - however this is hardly noticable for digital voice applications. - - TODO: logic to check if we are still in sync, ride thru bad frames - \*---------------------------------------------------------------------------*/ -void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[]) +void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin_frame) { COMP ch_symb[NSW*NSYMROWPILOT][COHPSK_NC*ND]; int i, j, sync, anext_sync, next_sync, nin, r, c; float max_ratio, f_est; - /* store two frames of received samples so we can rewind if we get a good candidate */ + next_sync = sync = coh->sync; - for (i=0; i<(NSW-1)*NSYMROWPILOT*COHPSK_M; i++) - coh->ch_fdm_frame_buf[i] = coh->ch_fdm_frame_buf[i+NSYMROWPILOT*COHPSK_M]; + for (i=0; ich_fdm_frame_buf[i] = coh->ch_fdm_frame_buf[i+*nin_frame]; + //printf("nin_frame: %d i: %d i+nin_frame: %d\n", *nin_frame, i, i+*nin_frame); for (j=0; ich_fdm_frame_buf[i] = rx_fdm[j]; //printf("i: %d j: %d rx_fdm[0]: %f %f\n", i,j, rx_fdm[0].real, rx_fdm[0].imag); - next_sync = sync = coh->sync; - nin = COHPSK_M; - - /* if out of sync do Initial Freq offset estimation using NSW frames to flush out filter memories */ + /* if out of sync do Initial Freq offset estimation using NSW frames to flush out filter memories */ if (sync == 0) { @@ -893,7 +901,7 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM /* we are out of sync so reset f_est and process two frames to clean out memories */ - rate_Fs_rx_processing(coh, ch_symb, coh->ch_fdm_frame_buf, &coh->f_est, NSW*NSYMROWPILOT, nin, 0); + rate_Fs_rx_processing(coh, ch_symb, coh->ch_fdm_frame_buf, &coh->f_est, NSW*NSYMROWPILOT, COHPSK_M, 0); for (i=0; ict_symb_buf, &ch_symb[i*NSYMROWPILOT]); } @@ -918,7 +926,7 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM fprintf(stderr, " [%d] trying sync and f_est: %f\n", coh->frame, coh->f_est); - rate_Fs_rx_processing(coh, ch_symb, coh->ch_fdm_frame_buf, &coh->f_est, NSW*NSYMROWPILOT, nin, 0); + rate_Fs_rx_processing(coh, ch_symb, coh->ch_fdm_frame_buf, &coh->f_est, NSW*NSYMROWPILOT, COHPSK_M, 0); for (i=0; ict_symb_buf, &ch_symb[i*NSYMROWPILOT]); } @@ -954,7 +962,7 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM /* If in sync just do sample rate processing on latest frame */ if (sync == 1) { - rate_Fs_rx_processing(coh, ch_symb, rx_fdm, &coh->f_est, NSYMROWPILOT, nin, 1); + rate_Fs_rx_processing(coh, ch_symb, rx_fdm, &coh->f_est, NSYMROWPILOT, coh->nin, 1); frame_sync_fine_freq_est(coh, ch_symb, sync, &next_sync); for(r=0; r<2; r++) @@ -975,4 +983,18 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM sync = sync_state_machine(coh, sync, next_sync); coh->sync = sync; + + /* work out how many samples we need for the next call to account + for differences in tx and rx sample clocks */ + + nin = COHPSK_M; + if (sync == 1) { + if (coh->rx_timing > COHPSK_M/P) + nin = COHPSK_M + COHPSK_M/P; + if (coh->rx_timing < -COHPSK_M/P) + nin = COHPSK_M - COHPSK_M/P; + } + coh->nin = nin; + *nin_frame = (NSYMROWPILOT-1)*COHPSK_M + nin; + //printf("%f %d %d\n", coh->rx_timing, nin, *nin_frame); } diff --git a/codec2-dev/src/cohpsk_internal.h b/codec2-dev/src/cohpsk_internal.h index 4f580137..c98c580b 100644 --- a/codec2-dev/src/cohpsk_internal.h +++ b/codec2-dev/src/cohpsk_internal.h @@ -51,7 +51,9 @@ struct COHPSK { float f_est; COMP rx_filter_memory[COHPSK_NC*ND][COHPSK_NFILTER]; COMP ct_symb_buf[NCT_SYMB_BUF][COHPSK_NC*ND]; - int ct; /* coarse timing offset in symbols */ + int ct; /* coarse timing offset in symbols */ + float rx_timing; /* fine timing for last symbol in frame */ + int nin; /* number of samples to input for next symbol */ float f_fine_est; COMP ff_rect; COMP ff_phase; @@ -64,19 +66,22 @@ struct COHPSK { struct FDMDV *fdmdv; - /* optional log variables used for tetsing Octave to C port */ + /* optional log variables used for testing Octave to C port */ - COMP *rx_baseband_log; + COMP *rx_baseband_log; int rx_baseband_log_col_index; int rx_baseband_log_col_sz; - COMP *rx_filt_log; + COMP *rx_filt_log; int rx_filt_log_col_index; int rx_filt_log_col_sz; - COMP *ch_symb_log; + COMP *ch_symb_log; int ch_symb_log_r; int ch_symb_log_col_sz; + + float *rx_timing_log; + int rx_timing_log_index; }; void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*COHPSK_ND], int tx_bits[], int nbits); diff --git a/codec2-dev/unittest/tcohpsk.c b/codec2-dev/unittest/tcohpsk.c index 41774895..7b16e4f0 100644 --- a/codec2-dev/unittest/tcohpsk.c +++ b/codec2-dev/unittest/tcohpsk.c @@ -99,6 +99,7 @@ int main(int argc, char *argv[]) float EsNo, variance; COMP scaled_noise; int reliable_sync_bit; + int ch_fdm_frame_log_index, nin_frame, tmp; coh = cohpsk_create(); fdmdv = coh->fdmdv; @@ -114,6 +115,8 @@ int main(int argc, char *argv[]) coh->ch_symb_log_col_sz = COHPSK_NC*ND; coh->ch_symb_log = (COMP *)malloc(sizeof(COMP)*NSYMROWPILOT*FRAMESL*coh->ch_symb_log_col_sz); + + coh->rx_timing_log = (float*)malloc(sizeof(float)*NSYMROWPILOT*FRAMESL); /* init stuff */ @@ -136,7 +139,6 @@ int main(int argc, char *argv[]) /* Main Loop ---------------------------------------------------------------------*/ for(f=0; fframe = f; /* --------------------------------------------------------*\ Mod @@ -176,27 +178,39 @@ int main(int argc, char *argv[]) ch_fdm_frame[r] = cadd(ch_fdm_frame[r], scaled_noise); } - - /* --------------------------------------------------------*\ - Demod - \*---------------------------------------------------------*/ - - cohpsk_demod(coh, rx_bits, &reliable_sync_bit, ch_fdm_frame); - - /* --------------------------------------------------------*\ - Log each vector - \*---------------------------------------------------------*/ + /* tx vector logging */ memcpy(&tx_bits_log[COHPSK_BITS_PER_FRAME*f], tx_bits, sizeof(int)*COHPSK_BITS_PER_FRAME); memcpy(&tx_fdm_frame_log[COHPSK_M*NSYMROWPILOT*f], tx_fdm_frame, sizeof(COMP)*COHPSK_M*NSYMROWPILOT); memcpy(&ch_fdm_frame_log[COHPSK_M*NSYMROWPILOT*f], ch_fdm_frame, sizeof(COMP)*COHPSK_M*NSYMROWPILOT); - //memcpy(&rx_fdm_frame_bb_log[M*NSYMROWPILOT*f], rx_fdm_frame_bb, sizeof(COMP)*M*NSYMROWPILOT); - + for(r=0; rframe = f; + + //printf("nin_frame: %d\n", nin_frame); + + /* --------------------------------------------------------*\ + Demod + \*---------------------------------------------------------*/ + + assert(ch_fdm_frame_log_index < COHPSK_M*NSYMROWPILOT*FRAMES); + tmp = nin_frame; + cohpsk_demod(coh, rx_bits, &reliable_sync_bit, &ch_fdm_frame_log[ch_fdm_frame_log_index], &nin_frame); + ch_fdm_frame_log_index += tmp; + + /* --------------------------------------------------------*\ + Log each vector + \*---------------------------------------------------------*/ if (coh->sync == 1) { @@ -242,6 +256,7 @@ int main(int argc, char *argv[]) octave_save_complex(fout, "rx_baseband_log_c", (COMP*)coh->rx_baseband_log, COHPSK_NC*ND, coh->rx_baseband_log_col_index, coh->rx_baseband_log_col_sz); octave_save_complex(fout, "rx_filt_log_c", (COMP*)coh->rx_filt_log, COHPSK_NC*ND, coh->rx_filt_log_col_index, coh->rx_filt_log_col_sz); octave_save_complex(fout, "ch_symb_log_c", (COMP*)coh->ch_symb_log, coh->ch_symb_log_r, COHPSK_NC*ND, COHPSK_NC*ND); + octave_save_float(fout, "rx_timing_log_c", (float*)coh->rx_timing_log, 1, coh->rx_timing_log_index, coh->rx_timing_log_index); octave_save_complex(fout, "ct_symb_ff_log_c", (COMP*)ct_symb_ff_log, NSYMROWPILOT*FRAMES, COHPSK_NC*ND, COHPSK_NC*ND); octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, log_data_r, COHPSK_NC*ND, COHPSK_NC*ND); octave_save_float(fout, "rx_phi_log_c", (float*)rx_phi_log, log_data_r, COHPSK_NC*ND, COHPSK_NC*ND); diff --git a/codec2-dev/unittest/test_cohpsk_ch.c b/codec2-dev/unittest/test_cohpsk_ch.c index 2ef6f3c5..cf4d6bbc 100644 --- a/codec2-dev/unittest/test_cohpsk_ch.c +++ b/codec2-dev/unittest/test_cohpsk_ch.c @@ -64,7 +64,7 @@ int main(int argc, char *argv[]) float EsNo, variance; COMP scaled_noise; float EsNodB, foff_hz; - int fading_en, nhfdelay, ret; + int fading_en, nhfdelay, ret, nin; COMP *ch_fdm_delay, aspread, aspread_2ms, delayed, direct; FILE *ffading; @@ -112,6 +112,8 @@ int main(int argc, char *argv[]) /* Main Loop ---------------------------------------------------------------------*/ + nin = COHPSK_SAMPLES_PER_FRAME; + for(f=0; f