coded up C part of freq offset estimation, now to test and debug
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 17 Mar 2018 20:11:20 +0000 (20:11 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 17 Mar 2018 20:11:20 +0000 (20:11 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3412 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/tofdm.m
codec2-dev/src/ofdm.c
codec2-dev/unittest/tofdm.c

index 73b99fea25db663ff782c78b04d5e123d7f29c3e..7d5747ac2bc891a9007d258b068e2c6a38cc4769 100644 (file)
@@ -149,8 +149,8 @@ check(tx_log, tx_log_c, 'tx');
 check(rx_log, rx_log_c, 'rx');
 check(rxbuf_in_log, rxbuf_in_log_c, 'rxbuf in');
 check(rxbuf_log, rxbuf_log_c, 'rxbuf');
-check(rx_sym_log, rx_sym_log_c, 'rx_sym');
-check(phase_est_pilot_log, phase_est_pilot_log_c, 'phase_est_pilot', tol=1E-3, its_an_angle=1);
+check(rx_sym_log, rx_sym_log_c, 'rx_sym', tol=5E-3);
+check(phase_est_pilot_log, phase_est_pilot_log_c, 'phase_est_pilot', tol=2E-3, its_an_angle=1);
 check(rx_amp_log, rx_amp_log_c, 'rx_amp');
 check(timing_est_log, timing_est_log_c, 'timing_est');
 check(sample_point_log, sample_point_log_c, 'sample_point');
index 52079af44edd8e9bab464bfd30c86b41a7b9ef0f..e128f911dee3e174268e413b9884ad93ae3a5221 100644 (file)
@@ -54,7 +54,7 @@ static complex float vector_sum(complex float *, int);
 static complex float qpsk_mod(int *);
 static void qpsk_demod(complex float, int *);
 static void ofdm_txframe(struct OFDM *, complex float [OFDM_SAMPLESPERFRAME], complex float *);
-static int coarse_sync(struct OFDM *, complex float *, int);
+static int coarse_sync(struct OFDM *, complex float *, int, float *foff_est);
 
 /* Defines */
 
@@ -146,15 +146,18 @@ static complex float vector_sum(complex float *a, int num_elements) {
  * Correlates the OFDM pilot symbol samples with a window of received
  * samples to determine the most likely timing offset.  Combines two
  * frames pilots so we need at least Nsamperframe+M+Ncp samples in rx.
+ *
+ * Also estimates coarse frequency offset based on sampling the pilots
+ * phase at half symbol intervales.
  */
 
-static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length) {
-    complex float csam;
+static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length, float *foff_est) {
+    complex float csam, csam1, csam2;
     int Ncorr = length - (OFDM_SAMPLESPERFRAME + (OFDM_M + OFDM_NCP));
     int Fs = OFDM_FS;
     int SFrame = OFDM_SAMPLESPERFRAME;
     float corr[Ncorr];
-    int i, j;
+    int i, j, k;
 
     for (i = 0; i < Ncorr; i++) {
         complex float temp = 0.0f + 0.0f * I;
@@ -180,14 +183,41 @@ static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length) {
         }
     }
 
-    /* Coarse frequency estimation */
-    /* TODO: Move FFT config to ofdm init and ofdm struct */
-    kiss_fft_cfg fftcfg = kiss_fft_alloc(Fs,0,NULL,NULL);
-    complex float fft_in[Fs];
-    complex float fft_out[Fs];
+    /* Coarse frequency estimation - note this isn't always used, some CPU could be saved
+       buy putting this in another function */
+
+    complex float p1, p2, p3, p4;
+    p1 = p2 = p3 = p4 =  0.0f + 0.0f * I;
     
+    /* calculate phase of pilots at half symbol intervals */
     
+    for (j = 0, k = (OFDM_M + OFDM_NCP)/2; j < (OFDM_M + OFDM_NCP)/2; j++,k++) {
+        csam1 = conjf(ofdm->pilot_samples[j]);
+        csam2 = conjf(ofdm->pilot_samples[k]);
+
+        /* pilot at start of frame */
+        
+        p1 = p1 + (rx[t_est + j] * csam1);
+        p2 = p2 + (rx[t_est + k] * csam1);
+
+        /* pilot at end of frame */
+        
+        p3 = p3 + (rx[t_est + j + SFrame] * csam2);
+        p4 = p4 + (rx[t_est + k + SFrame] * csam2);
+    }
 
+    /* Calculate sample rate of phase samples, we are sampling phase
+       of pilot at half a symbol intervals */
+    
+    float Fs1 = Fs/((OFDM_M + OFDM_NCP)/2);
+
+    /* subtract phase of adjacent samples, rate of change of phase is
+       frequency est.  We combine samples from either end of frame to
+       improve estimate.  Small real 1E-12 term to prevent instability
+       with 0 inputs. */
+    
+    *foff_est = Fs1 * cargf(conjf(p1)*p2 + conjf(p3)*p4 + 1E-12)/(2.0*M_PI);
+   
     return t_est;
 }
 
@@ -434,7 +464,7 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) {
     complex float aphase_est_pilot_rect;
     float aphase_est_pilot[OFDM_NC + 2];
     float aamp_est_pilot[OFDM_NC + 2];
-    float freq_err_hz;
+    float freq_err_hz, coarse_foff_est;
     int i, j, k, rr, st, en, ft_est;
 
     /* shift the buffer left based on nin */
@@ -474,7 +504,9 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) {
             work[j] = ofdm->rxbuf[i] * cexpf(-I * woff_est * i);
         }
 
-        ft_est = coarse_sync(ofdm, work, (en - st));
+        /* note coarse sync just used for timing est, we dont use coarse_foff_est in this call */
+        
+        ft_est = coarse_sync(ofdm, work, (en - st), &coarse_foff_est);
         ofdm->timing_est += (ft_est - ceilf(OFDM_FTWINDOWWIDTH / 2));
 
         if (ofdm->verbose > 1) {
index 2ffff9a2a04d719ffaee78038917acec7c98c408..9a39d610d9b293c2e15edc90675db7bcb48a44ab 100644 (file)
@@ -269,7 +269,7 @@ int main(int argc, char *argv[])
         }
 
         foff_hz_log[f] = ofdm->foff_est_hz;
-        timing_est_log[f] = ofdm->timing_est + 1;      /* offset by 1 to match Octave */
+        timing_est_log[f] = ofdm->timing_est + 1;     /* offset by 1 to match Octave */
         sample_point_log[f] = ofdm->sample_point + 1; /* offset by 1 to match Octave */
 
         memcpy(&rx_bits_log[OFDM_BITSPERFRAME*f], rx_bits, sizeof(rx_bits));