From 7ff119e6f2ffaab427a37ebfa68667d968d3bfbe Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sun, 5 Apr 2015 08:07:19 +0000 Subject: [PATCH] written coh mod and demod but not tested git-svn-id: https://svn.code.sf.net/p/freetel/code@2103 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/tcohpsk.m | 35 ++++---- codec2-dev/src/codec2_cohpsk.h | 8 +- codec2-dev/src/cohpsk.c | 123 +++++++++++++++++++++++++++- codec2-dev/src/cohpsk_internal.h | 5 ++ codec2-dev/unittest/noise_samples.h | 51 +----------- codec2-dev/unittest/tcohpsk.c | 27 ++---- 6 files changed, 155 insertions(+), 94 deletions(-) diff --git a/codec2-dev/octave/tcohpsk.m b/codec2-dev/octave/tcohpsk.m index de25f5ea..64b210b0 100644 --- a/codec2-dev/octave/tcohpsk.m +++ b/codec2-dev/octave/tcohpsk.m @@ -53,7 +53,7 @@ Rs = 50; Nc = 4; framesize = 32; -% -------------------------------------------------------------------------- +% FDMDV init --------------------------------------------------------------- afdmdv.Fs = 8000; afdmdv.Nc = Nc-1; @@ -90,9 +90,7 @@ afdmdv.Nfiltertiming = afdmdv.M + afdmdv.Nfilter + afdmdv.M; afdmdv.rx_filter_memory = zeros(afdmdv.Nc+1, afdmdv.Nfilter); -% --------------------------------------------------------- - -load ../build_linux/unittest/tcohpsk_out.txt +% COHPSK Init -------------------------------------------------------- acohpsk = standard_init(); acohpsk.framesize = framesize; @@ -110,10 +108,6 @@ acohpsk.f_est = afdmdv.Fcentre; % ----------------------------------------------------------- -rand('state',1); -tx_bits_coh = round(rand(1,framesize*10)); -ptx_bits_coh = 1; - tx_bits_log = []; tx_symb_log = []; rx_amp_log = []; @@ -128,26 +122,27 @@ 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); - -ch_symb = zeros(acohpsk.Nsymbrowpilot, acohpsk.Nc); - -Nerrs = Tbits = 0; - rx_filt_log = []; rx_fdm_filter_log = []; rx_baseband_log = []; rx_fdm_frame_log = []; -f_err_log = []; -f_err_fail = 0; ct_symb_ff_log = []; +% BER measurement ------------------------------------------------------------- + +rand('state',1); +tx_bits_coh = round(rand(1,framesize*10)); +ptx_bits_coh = 1; + +Nerrs = Tbits = 0; +prev_tx_bits = []; + phase_ch = 1; sync = 0; -prev_tx_bits = []; +% Output vectors from C port --------------------------------------------------- + +load ../build_linux/unittest/tcohpsk_out.txt % main loop -------------------------------------------------------------------- @@ -212,7 +207,7 @@ for i=1:frames ch_symb = zeros(acohpsk.Nsymbrowpilot, Nc); for r=1:acohpsk.Nsymbrowpilot - % donwconvert each FDM carrier to Nc separate baseband signals + % downconvert each FDM carrier to Nc separate baseband signals [rx_baseband afdmdv] = fdm_downconvert(afdmdv, rx_fdm_frame_bb(1+(r-1)*M:r*M), nin); rx_baseband_log = [rx_baseband_log rx_baseband]; diff --git a/codec2-dev/src/codec2_cohpsk.h b/codec2-dev/src/codec2_cohpsk.h index 60acc0dd..8fdad615 100644 --- a/codec2-dev/src/codec2_cohpsk.h +++ b/codec2-dev/src/codec2_cohpsk.h @@ -28,8 +28,9 @@ #ifndef __CODEC2_COHPSK__ #define __CODEC2_COHPSK__ -#define COHPSK_BITS_PER_FRAME 32 /* hard coded for now */ -#define COHPSK_NC 4 /* hard coded for now */ +#define COHPSK_BITS_PER_FRAME 32 /* hard coded for now */ +#define COHPSK_NC 4 /* hard coded for now */ +#define COHPSK_SAMPLES_PER_FRAME (NSYMROWPILOT*M) #include "comp.h" #include "codec2_fdmdv.h" @@ -45,4 +46,7 @@ void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC], int void fine_freq_correct(struct COHPSK *coh, int sync, int next_sync); int sync_state_machine(int sync, int next_sync); +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[]); + #endif diff --git a/codec2-dev/src/cohpsk.c b/codec2-dev/src/cohpsk.c index 89ec8764..277712f7 100644 --- a/codec2-dev/src/cohpsk.c +++ b/codec2-dev/src/cohpsk.c @@ -75,7 +75,9 @@ static COMP qpsk_mod[] = { struct COHPSK *cohpsk_create(void) { struct COHPSK *coh; - int r,c,p; + struct FDMDV *fdmdv; + int r,c,p,i; + float freq_hz; coh = (struct COHPSK*)malloc(sizeof(struct COHPSK)); if (coh == NULL) @@ -106,6 +108,27 @@ struct COHPSK *cohpsk_create(void) } coh->ff_phase.real = 1.0; coh->ff_phase.imag = 0.0; + coh->sync = 0; + + /* set up fdmdv states so we can use those modem functions */ + + fdmdv = fdmdv_create(PILOTS_NC - 1); + for(c=0; cphase_tx[c].real = 1.0; + fdmdv->phase_tx[c].imag = 0.0; + + freq_hz = fdmdv->fsep*( -PILOTS_NC/2 - 0.5 + c + 1.0 ); + fdmdv->freq[c].real = cosf(2.0*M_PI*freq_hz/FS); + fdmdv->freq[c].imag = sinf(2.0*M_PI*freq_hz/FS); + fdmdv->freq_pol[c] = 2.0*M_PI*freq_hz/FS; + + //printf("c: %d %f %f\n",c,freq_hz,fdmdv->freq_pol[c]); + for(i=0; irx_filter_memory[c][i].real = 0.0; + coh->rx_filter_memory[c][i].imag = 0.0; + } + } + coh->fdmdv = fdmdv; return coh; } @@ -123,6 +146,7 @@ struct COHPSK *cohpsk_create(void) void cohpsk_destroy(struct COHPSK *coh) { + fdmdv_destroy(coh->fdmdv); KISS_FFT_FREE(coh->fft_coarse_fest); assert(coh != NULL); free(coh); @@ -455,4 +479,101 @@ int sync_state_machine(int sync, int next_sync) } +/*---------------------------------------------------------------------------*\ + + FUNCTION....: cohpsk_mod() + AUTHOR......: David Rowe + DATE CREATED: 5/4/2015 + + COHPSK modulator, take a frame of COHPSK_BITS_PER_FRAME bits and + generates a frame of COHPSK_SAMPLES_PER_FRAME modulated symbols. + + The output signal is complex to support single sided frequency + shifting, for example when testing frequency offsets in channel + simulation. +\*---------------------------------------------------------------------------*/ + +void cohpsk_mod(struct COHPSK *coh, COMP tx_fdm[], int tx_bits[]) +{ + struct FDMDV *fdmdv = coh->fdmdv; + COMP tx_symb[NSYMROWPILOT][PILOTS_NC]; + COMP tx_onesym[PILOTS_NC]; + int r,c; + + bits_to_qpsk_symbols(tx_symb, tx_bits, COHPSK_BITS_PER_FRAME); + + for(r=0; rNc , tx_onesym, fdmdv->tx_filter_memory, + fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect); + } +} + + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: cohpsk_demod() + 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. + + 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[]) +{ + struct FDMDV *fdmdv = coh->fdmdv; + COMP rx_fdm_frame_bb[M*NSYMROWPILOT]; + COMP rx_baseband[PILOTS_NC][M+M/P]; + COMP rx_filt[PILOTS_NC][P+1]; + float env[NT*P], rx_timing; + COMP ch_symb[NSYMROWPILOT][PILOTS_NC]; + COMP rx_onesym[PILOTS_NC]; + int sync, next_sync, nin, r, c; + + next_sync = sync = coh->sync; + + coarse_freq_offset_est(coh, fdmdv, rx_fdm, sync, &next_sync); + + /* sample rate demod processing */ + + nin = M; + for (r=0; rf_est, &fdmdv->fbb_phase_rx, nin); + fdm_downconvert(rx_baseband, fdmdv->Nc, &rx_fdm_frame_bb[r*M], fdmdv->phase_rx, fdmdv->freq, nin); + rx_filter(rx_filt, fdmdv->Nc, 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); + + for(c=0; cct_symb_ff_buf); + *reliable_sync_bit = 1; + } + + sync = sync_state_machine(sync, next_sync); + + coh->sync = sync; +} diff --git a/codec2-dev/src/cohpsk_internal.h b/codec2-dev/src/cohpsk_internal.h index 4f5a7222..8925f43c 100644 --- a/codec2-dev/src/cohpsk_internal.h +++ b/codec2-dev/src/cohpsk_internal.h @@ -31,6 +31,7 @@ #define COARSE_FEST_NDFT 1024 #define NCT_SYMB_BUF (2*NSYMROWPILOT+2) +#include "fdmdv_internal.h" #include "kiss_fft.h" struct COHPSK { @@ -40,12 +41,16 @@ struct COHPSK { COMP rx_symb[NSYMROW][PILOTS_NC]; /* demodulated symbols */ kiss_fft_cfg fft_coarse_fest; float f_est; + COMP rx_filter_memory[PILOTS_NC][NFILTER]; COMP ct_symb_buf[NCT_SYMB_BUF][PILOTS_NC]; int ct; /* coarse timing offset in symbols */ float f_fine_est; COMP ff_rect; COMP ff_phase; COMP ct_symb_ff_buf[NSYMROWPILOT+2][PILOTS_NC]; + int sync; + + struct FDMDV *fdmdv; }; diff --git a/codec2-dev/unittest/noise_samples.h b/codec2-dev/unittest/noise_samples.h index d31a1484..fbf2fa69 100644 --- a/codec2-dev/unittest/noise_samples.h +++ b/codec2-dev/unittest/noise_samples.h @@ -33601,53 +33601,4 @@ COMP noise[]={ {-2.201099,8.147500}, {-0.854860,-3.217227}, {2.865000,3.780455} -};03688}, - {3.947704,2.591331}, - {-13.355771,-1.640064}, - {-6.981492,2.597217}, - {-3.238346,-5.647247}, - {-6.181055,1.810279}, - {-3.202626,-1.235126}, - {-3.157657,-5.482706}, - {-2.648149,0.392058}, - {-0.511225,-0.631106}, - {2.175415,0.068423}, - {4.481758,2.334373}, - {2.427512,6.953592}, - {-3.374617,3.710045}, - {-1.207558,0.621048}, - {-0.177510,-0.751545}, - {5.995835,-4.081549}, - {3.144007,-0.692084}, - {17.133404,0.486124}, - {3.646924,-4.741484}, - {2.323303,1.063447}, - {-2.397030,5.749218}, - {-3.236087,-2.329649}, - {-4.288638,3.571241}, - {-6.484552,1.256784}, - {-7.055667,0.299616}, - {-0.975544,-2.110141}, - {-6.905026,3.049075}, - {-6.688080,-2.805814}, - {-1.846770,-10.936074}, - {-3.303769,4.626817}, - {4.776190,1.080799}, - {-3.797495,-1.150984}, - {-3.722335,4.753599}, - {-0.111050,1.675908}, - {-2.614292,-2.621500}, - {-5.546542,10.839913}, - {2.920223,0.688586}, - {5.758427,6.683944}, - {-7.829388,-8.163553}, - {-3.567825,2.562626}, - {-4.198519,3.407382}, - {-4.599247,6.985142}, - {1.677356,1.667125}, - {-2.453346,-2.577718}, - {-6.986411,-3.614714}, - {-2.331341,-2.549597}, - {-7.382277,-0.327108}, - {6.535084,-3.545155}, - {0.437164,4.358225}, +}; \ No newline at end of file diff --git a/codec2-dev/unittest/tcohpsk.c b/codec2-dev/unittest/tcohpsk.c index 9adf872a..4d9f050b 100644 --- a/codec2-dev/unittest/tcohpsk.c +++ b/codec2-dev/unittest/tcohpsk.c @@ -97,6 +97,7 @@ int main(int argc, char *argv[]) int sync, next_sync, log_bits; coh = cohpsk_create(); + fdmdv = coh->fdmdv; assert(coh != NULL); log_r = log_data_r = noise_r = log_bits = 0; @@ -108,25 +109,6 @@ int main(int argc, char *argv[]) phase_ch.real = 1.0; phase_ch.imag = 0.0; sync = 0; - /* set up fdmdv states so we can use those modem functions */ - - fdmdv = fdmdv_create(PILOTS_NC - 1); - for(c=0; cphase_tx[c].real = 1.0; - fdmdv->phase_tx[c].imag = 0.0; - - freq_hz = fdmdv->fsep*( -PILOTS_NC/2 - 0.5 + c + 1.0 ); - fdmdv->freq[c].real = cosf(2.0*M_PI*freq_hz/FS); - fdmdv->freq[c].imag = sinf(2.0*M_PI*freq_hz/FS); - fdmdv->freq_pol[c] = 2.0*M_PI*freq_hz/FS; - - //printf("c: %d %f %f\n",c,freq_hz,fdmdv->freq_pol[c]); - for(i=0; iphase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect); } + /* --------------------------------------------------------*\ + Channel + \*---------------------------------------------------------*/ + fdmdv_freq_shift(ch_fdm_frame, tx_fdm_frame, FOFF, &phase_ch, NSYMROWPILOT*M); for(r=0; rf_est, &fdmdv->fbb_phase_rx, nin); fdm_downconvert(rx_baseband, fdmdv->Nc, &rx_fdm_frame_bb[r*M], fdmdv->phase_rx, fdmdv->freq, nin); - rx_filter(rx_filt, fdmdv->Nc, rx_baseband, rx_filter_memory, nin); + rx_filter(rx_filt, fdmdv->Nc, 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); for(c=0; c