From: drowe67 Date: Thu, 23 Feb 2017 03:35:46 +0000 (+0000) Subject: added support for measuring bit errors before diversity combination, part of 700C... X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=671e949ba4dbe7c7f782b289af45b14219e45316;p=freetel-svn-tracking.git added support for measuring bit errors before diversity combination, part of 700C instrumentation git-svn-id: https://svn.code.sf.net/p/freetel/code@3047 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/src/codec2_cohpsk.h b/codec2-dev/src/codec2_cohpsk.h index b64cde84..5520ec79 100644 --- a/codec2-dev/src/codec2_cohpsk.h +++ b/codec2-dev/src/codec2_cohpsk.h @@ -53,9 +53,15 @@ void cohpsk_get_demod_stats(struct COHPSK *cohpsk, struct MODEM_STATS *stats); void cohpsk_set_verbose(struct COHPSK *coh, int verbose); void cohpsk_get_test_bits(struct COHPSK *coh, int rx_bits[]); void cohpsk_put_test_bits(struct COHPSK *coh, int *state, short error_pattern[], - int *bit_errors, char rx_bits[]); + int *bit_errors, char rx_bits[], int channel); int cohpsk_error_pattern_size(void); void cohpsk_set_frame(struct COHPSK *coh, int frame); void fdmdv_freq_shift_coh(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, float Fs, COMP *foff_phase_rect, int nin); + +/* used for accessing upper and lower bits before diversity combination */ + +float *cohpsk_get_rx_bits_lower(struct COHPSK *coh); +float *cohpsk_get_rx_bits_upper(struct COHPSK *coh); + #endif diff --git a/codec2-dev/src/cohpsk.c b/codec2-dev/src/cohpsk.c index 83f155c5..58d13b29 100644 --- a/codec2-dev/src/cohpsk.c +++ b/codec2-dev/src/cohpsk.c @@ -181,7 +181,7 @@ struct COHPSK *cohpsk_create(void) /* test frames */ - coh->ptest_bits_coh_tx = coh->ptest_bits_coh_rx = (int*)test_bits_coh; + coh->ptest_bits_coh_tx = coh->ptest_bits_coh_rx[0] = coh->ptest_bits_coh_rx[1] = (int*)test_bits_coh; coh->ptest_bits_coh_end = (int*)test_bits_coh + sizeof(test_bits_coh)/sizeof(int); return coh; @@ -362,6 +362,18 @@ void qpsk_symbols_to_bits(struct COHPSK *coh, float rx_bits[], COMP ct_symb_buf[ i = c*NSYMROW + r; rx_bits[2*i+1] = rot.real; rx_bits[2*i] = rot.imag; + + /* demodulate bits from upper and lower carriers separately for test purposes */ + + assert(ND == 2); + + i = c*NSYMROW + r; + rot = cmult(coh->rx_symb[r][c], pi_on_4); + coh->rx_bits_lower[2*i+1] = rot.real; + coh->rx_bits_lower[2*i] = rot.imag; + rot = cmult(coh->rx_symb[r][c + COHPSK_NC], pi_on_4); + coh->rx_bits_upper[2*i+1] = rot.real; + coh->rx_bits_upper[2*i] = rot.imag; } } @@ -1195,23 +1207,29 @@ void cohpsk_get_test_bits(struct COHPSK *coh, int rx_bits[]) Accepts bits from demod and attempts to sync with the known test_bits sequence. When synced measures bit errors. + Has states to track two separate received test sequences based on + channel 0 or 1. + \*---------------------------------------------------------------------------*/ void cohpsk_put_test_bits(struct COHPSK *coh, int *state, short error_pattern[], - int *bit_errors, char rx_bits_char[]) + int *bit_errors, char rx_bits_char[], int channel) { int i, next_state, anerror; int rx_bits[COHPSK_BITS_PER_FRAME]; + assert((channel == 0) || (channel == 1)); + int *ptest_bits_coh_rx = coh->ptest_bits_coh_rx[channel]; + for(i=0; iptest_bits_coh_rx[i]; + anerror = (rx_bits[i] & 0x1) ^ ptest_bits_coh_rx[i]; if ((anerror < 0) || (anerror > 1)) { - fprintf(stderr, "i: %d rx_bits: %d ptest_bits_coh_rx: %d\n", i, rx_bits[i], coh->ptest_bits_coh_rx[i]); + fprintf(stderr, "i: %d rx_bits: %d ptest_bits_coh_rx: %d\n", i, rx_bits[i], ptest_bits_coh_rx[i]); } *bit_errors += anerror; error_pattern[i] = anerror; @@ -1224,9 +1242,9 @@ void cohpsk_put_test_bits(struct COHPSK *coh, int *state, short error_pattern[], if (*state == 0) { if (*bit_errors < 4) { next_state = 1; - coh->ptest_bits_coh_rx += COHPSK_BITS_PER_FRAME; - if (coh->ptest_bits_coh_rx >= coh->ptest_bits_coh_end) { - coh->ptest_bits_coh_rx = (int*)test_bits_coh; + ptest_bits_coh_rx += COHPSK_BITS_PER_FRAME; + if (ptest_bits_coh_rx >= coh->ptest_bits_coh_end) { + ptest_bits_coh_rx = (int*)test_bits_coh; } } } @@ -1245,19 +1263,30 @@ void cohpsk_put_test_bits(struct COHPSK *coh, int *state, short error_pattern[], } if (*state > 0) { - coh->ptest_bits_coh_rx += COHPSK_BITS_PER_FRAME; - if (coh->ptest_bits_coh_rx >= coh->ptest_bits_coh_end) { - coh->ptest_bits_coh_rx = (int*)test_bits_coh; + ptest_bits_coh_rx += COHPSK_BITS_PER_FRAME; + if (ptest_bits_coh_rx >= coh->ptest_bits_coh_end) { + ptest_bits_coh_rx = (int*)test_bits_coh; } } //fprintf(stderr, "state: %d next_state: %d bit_errors: %d\n", *state, next_state, *bit_errors); *state = next_state; + coh->ptest_bits_coh_rx[channel] = ptest_bits_coh_rx; } + int cohpsk_error_pattern_size(void) { return COHPSK_BITS_PER_FRAME; } +float *cohpsk_get_rx_bits_lower(struct COHPSK *coh) { + return coh->rx_bits_lower; +} + + +float *cohpsk_get_rx_bits_upper(struct COHPSK *coh) { + return coh->rx_bits_upper; +} + diff --git a/codec2-dev/src/cohpsk_demod.c b/codec2-dev/src/cohpsk_demod.c index 875cc7e8..e05e7c84 100644 --- a/codec2-dev/src/cohpsk_demod.c +++ b/codec2-dev/src/cohpsk_demod.c @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) } cohpsk = cohpsk_create(); - cohpsk_set_verbose(cohpsk, 1); + cohpsk_set_verbose(cohpsk, 0); if (oct) { logframes = LOG_FRAMES; diff --git a/codec2-dev/src/cohpsk_internal.h b/codec2-dev/src/cohpsk_internal.h index b77aff0b..e8ce5541 100644 --- a/codec2-dev/src/cohpsk_internal.h +++ b/codec2-dev/src/cohpsk_internal.h @@ -46,9 +46,9 @@ struct COHPSK { COMP ch_fdm_frame_buf[NSW*NSYMROWPILOT*COHPSK_M]; /* buffer of several frames of symbols from channel */ float pilot2[2*NPILOTSFRAME][COHPSK_NC]; - float phi_[NSYMROW][COHPSK_NC*ND]; /* phase estimates for this frame of rx data symbols */ + float phi_[NSYMROWPILOT][COHPSK_NC*ND]; /* phase estimates for this frame of rx data symbols */ float amp_[NSYMROW][COHPSK_NC*ND]; /* amplitude estimates for this frame of rx data symbols */ - COMP rx_symb[NSYMROW][COHPSK_NC*ND]; /* demodulated symbols */ + COMP rx_symb[NSYMROWPILOT][COHPSK_NC*ND]; /* demodulated symbols */ float f_est; COMP rx_filter_memory[COHPSK_NC*ND][COHPSK_NFILTER]; COMP ct_symb_buf[NCT_SYMB_BUF][COHPSK_NC*ND]; @@ -73,9 +73,14 @@ struct COHPSK { int verbose; int *ptest_bits_coh_tx; - int *ptest_bits_coh_rx; + int *ptest_bits_coh_rx[2]; int *ptest_bits_coh_end; + /* counting bit errors using pilots */ + + int npilotbits; + int npilotbiterrors; + /* optional log variables used for testing Octave to C port */ COMP *rx_baseband_log; @@ -92,6 +97,11 @@ struct COHPSK { float *rx_timing_log; int rx_timing_log_index; + + /* demodulated bits before diversity combination for test/instrumentation purposes */ + + float rx_bits_lower[COHPSK_BITS_PER_FRAME]; + float rx_bits_upper[COHPSK_BITS_PER_FRAME]; }; void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*COHPSK_ND], int tx_bits[], int nbits); diff --git a/codec2-dev/src/cohpsk_put_test_bits.c b/codec2-dev/src/cohpsk_put_test_bits.c index aa2c4e80..d2f6d198 100644 --- a/codec2-dev/src/cohpsk_put_test_bits.c +++ b/codec2-dev/src/cohpsk_put_test_bits.c @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) state = 0; nbits = 0; nerrors = 0; while (fread(rx_bits, sizeof(char), COHPSK_BITS_PER_FRAME, fin) == COHPSK_BITS_PER_FRAME) { - cohpsk_put_test_bits(coh, &state, error_pattern, &bit_errors, rx_bits); + cohpsk_put_test_bits(coh, &state, error_pattern, &bit_errors, rx_bits, 0); if (state == 1) { for(i=0; isz_error_pattern = cohpsk_error_pattern_size(); } #endif - if ((mode == FREEDV_MODE_2400A) || (mode == FREEDV_MODE_2400B)){ + if ((mode == FREEDV_MODE_2400A) || (mode == FREEDV_MODE_2400B)) { /* Set up the C2 mode */ codec2_mode = CODEC2_MODE_1300; @@ -246,7 +246,9 @@ struct freedv *freedv_open(int mode) { } + f->test_frames_diversity = 1; f->test_frame_sync_state = 0; + f->test_frame_sync_state_upper = 0; f->total_bits = 0; f->total_bit_errors = 0; @@ -1229,21 +1231,63 @@ static int freedv_comprx_fdmdv_700(struct freedv *f, COMP demod_in_8kHz[], int * nout = f->n_speech_samples; } else { - short error_pattern[COHPSK_BITS_PER_FRAME]; - int bit_errors; - - /* test data, lets see if we can sync to the test data sequence */ - - char rx_bits_char[COHPSK_BITS_PER_FRAME]; - for(i=0; icohpsk, &f->test_frame_sync_state, error_pattern, &bit_errors, rx_bits_char); - if (f->test_frame_sync_state) { - f->total_bit_errors += bit_errors; - f->total_bits += COHPSK_BITS_PER_FRAME; - if (f->freedv_put_error_pattern != NULL) { - (*f->freedv_put_error_pattern)(f->error_pattern_callback_state, error_pattern, COHPSK_BITS_PER_FRAME); + //fprintf(stderr, " freedv_api: f->test_frames_diversity: %d\n", f->test_frames_diversity); + + if (f->test_frames_diversity) { + /* normal operation - error pattern on frame after diveristy combination */ + short error_pattern[COHPSK_BITS_PER_FRAME]; + int bit_errors; + + /* test data, lets see if we can sync to the test data sequence */ + + char rx_bits_char[COHPSK_BITS_PER_FRAME]; + for(i=0; icohpsk, &f->test_frame_sync_state, error_pattern, &bit_errors, rx_bits_char, 0); + if (f->test_frame_sync_state) { + f->total_bit_errors += bit_errors; + f->total_bits += COHPSK_BITS_PER_FRAME; + if (f->freedv_put_error_pattern != NULL) { + (*f->freedv_put_error_pattern)(f->error_pattern_callback_state, error_pattern, COHPSK_BITS_PER_FRAME); + } + } + } + else { + /* calculate error pattern on uncombined carriers - test mode to spot any carrier specific issues like + tx passband filtering */ + + short error_pattern[2*COHPSK_BITS_PER_FRAME]; + char rx_bits_char[COHPSK_BITS_PER_FRAME]; + int bit_errors_lower, bit_errors_upper; + + /* lower group of carriers */ + + float *rx_bits_lower = cohpsk_get_rx_bits_lower(f->cohpsk); + for(i=0; icohpsk, &f->test_frame_sync_state, error_pattern, &bit_errors_lower, rx_bits_char, 0); + + /* upper group of carriers */ + + float *rx_bits_upper = cohpsk_get_rx_bits_upper(f->cohpsk); + for(i=0; icohpsk, &f->test_frame_sync_state_upper, &error_pattern[COHPSK_BITS_PER_FRAME], &bit_errors_upper, rx_bits_char, 1); + // fprintf(stderr, " freedv_api: f->test_frame_sync_state: %d f->test_frame_sync_state_upper: %d\n", + // f->test_frame_sync_state, f->test_frame_sync_state_upper); + + /* combine total errors and call callback */ + + if (f->test_frame_sync_state && f->test_frame_sync_state_upper) { + f->total_bit_errors += bit_errors_lower + bit_errors_upper; + f->total_bits += 2*COHPSK_BITS_PER_FRAME; + if (f->freedv_put_error_pattern != NULL) { + (*f->freedv_put_error_pattern)(f->error_pattern_callback_state, error_pattern, 2*COHPSK_BITS_PER_FRAME); + } } + } *valid = 0; @@ -1503,10 +1547,11 @@ void freedv_get_modem_stats(struct freedv *f, int *sync, float *snr_est) // Set integers void freedv_set_test_frames (struct freedv *f, int val) {f->test_frames = val;} +void freedv_set_test_frames_diversity (struct freedv *f, int val) {f->test_frames_diversity = val;} void freedv_set_squelch_en (struct freedv *f, int val) {f->squelch_en = val;} void freedv_set_total_bit_errors (struct freedv *f, int val) {f->total_bit_errors = val;} void freedv_set_total_bits (struct freedv *f, int val) {f->total_bits = val;} -void freedv_set_clip (struct freedv *f, int val) {f->clip = val;} +void freedv_set_clip (struct freedv *f, int val) {f->clip = val;} void freedv_set_varicode_code_num (struct freedv *f, int val) {varicode_set_code_num(&f->varicode_dec_states, val);} // Set floats @@ -1587,8 +1632,19 @@ int freedv_get_n_max_modem_samples (struct freedv *f) {return f->n_max_mo int freedv_get_n_nom_modem_samples (struct freedv *f) {return f->n_nom_modem_samples;} int freedv_get_total_bits (struct freedv *f) {return f->total_bits;} int freedv_get_total_bit_errors (struct freedv *f) {return f->total_bit_errors;} -int freedv_get_sync (struct freedv *f) {return f->stats.sync;} -int freedv_get_sz_error_pattern (struct freedv *f) {return f->sz_error_pattern;} +int freedv_get_sync (struct freedv *f) {return f->stats.sync;} + +int freedv_get_sz_error_pattern(struct freedv *f) +{ + if ((f->mode == FREEDV_MODE_700) || (f->mode == FREEDV_MODE_700B) || (f->mode == FREEDV_MODE_700C)) { + /* if diversity disabled callback sends error pattern for upper and lower carriers */ + return f->sz_error_pattern * (2 - f->test_frames_diversity); + } + else { + return f->sz_error_pattern; + } +} + // Get floats struct CODEC2 *freedv_get_codec2 (struct freedv *f){return f->codec2;} diff --git a/codec2-dev/src/freedv_api.h b/codec2-dev/src/freedv_api.h index 7691bab3..9d05d440 100644 --- a/codec2-dev/src/freedv_api.h +++ b/codec2-dev/src/freedv_api.h @@ -89,6 +89,7 @@ void freedv_set_callback_txt (struct freedv *freedv, freedv_callback_ void freedv_set_callback_protocol (struct freedv *freedv, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state); void freedv_set_callback_data (struct freedv *freedv, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state); void freedv_set_test_frames (struct freedv *freedv, int test_frames); +void freedv_set_test_frames_diversity (struct freedv *freedv, int test_frames_diversity); void freedv_set_smooth_symbols (struct freedv *freedv, int smooth_symbols); void freedv_set_squelch_en (struct freedv *freedv, int squelch_en); void freedv_set_snr_squelch_thresh (struct freedv *freedv, float snr_squelch_thresh); diff --git a/codec2-dev/src/freedv_api_internal.h b/codec2-dev/src/freedv_api_internal.h index b25e5811..7ef000cf 100644 --- a/codec2-dev/src/freedv_api_internal.h +++ b/codec2-dev/src/freedv_api_internal.h @@ -95,7 +95,9 @@ struct freedv { int *ptest_bits_coh_end; int test_frames; // set this baby for 1 to tx/rx test frames to look at bit error stats + int test_frames_diversity; // 1 -> used combined carriers for error counting on 700 waveforms int test_frame_sync_state; + int test_frame_sync_state_upper; // when test_frames_diveristy==0 we need extra states for upper carriers int test_frame_count; int total_bits; int total_bit_errors;