non linear carrier spacing and clipping code added, C and Octave match nicely
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 26 May 2015 07:28:08 +0000 (07:28 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 26 May 2015 07:28:08 +0000 (07:28 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2149 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/tcohpsk.m
codec2-dev/src/codec2_cohpsk.h
codec2-dev/src/cohpsk.c
codec2-dev/src/cohpsk_internal.h
codec2-dev/unittest/tcohpsk.c

index caa83b9e63f7f428244aedb9f3f8708d0adbe3cd..7364a06b49a7c60e455f095273aa90d4d82aab8a 100644 (file)
@@ -120,7 +120,7 @@ Nsw = 3;               % frames we demod for initial sync window
 afdmdv.Nsym = 6;       % size of tx/tx root nyquist filter in symbols
 afdmdv.Nt = 5;         % number of symbols we estimate timing over
 
-clip = 65;            % Clipping of tx signal to reduce PAPR. Adjust by 
+clip = 6.5;            % Clipping of tx signal to reduce PAPR. Adjust by 
                        % experiment as Nc and Nd change.  Check out no noise 
                        % scatter diagram and AWGN/fading BER perf
                        % at operating points
@@ -144,7 +144,8 @@ afdmdv.gt_alpha5_root = gen_rn_coeffs(excess_bw, 1/Fs, Rs, afdmdv.Nsym, afdmdv.M
 Fcentre = afdmdv.Fcentre = 1500;
 afdmdv.Fsep = afdmdv.Rs*(1+excess_bw);
 afdmdv.phase_tx = ones(afdmdv.Nc+1,1);
-freq_hz = afdmdv.Fsep*( -Nc*Nd/2 - 0.5 + (1:Nc*Nd).^1 );
+% non linear carrier spacing, combined with clip, helps PAPR a lot!
+freq_hz = afdmdv.Fsep*( -Nc*Nd/2 - 0.5 + (1:Nc*Nd).^0.98 ); 
 afdmdv.freq_pol = 2*pi*freq_hz/Fs;
 afdmdv.freq = exp(j*afdmdv.freq_pol);
 afdmdv.Fcentre = 1500;
index b4e227c52b2d3160553946fb27f56929e5703262..aa1ccbb2e9d351a8422b2b004d0f5598a4a3ae96 100644 (file)
@@ -42,6 +42,7 @@ 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_clip(COMP tx_fdm[]);
 void cohpsk_demod(struct COHPSK *cohpsk, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin_frame);
 
 #endif
index 5d04b4b4dfd492961148583570bc6c57d8e9584e..e26c310edbcf8e9ea40a585c2f425490a747d7ea 100644 (file)
@@ -135,13 +135,15 @@ struct COHPSK *cohpsk_create(void)
        fdmdv->phase_tx[c].real = 1.0;
        fdmdv->phase_tx[c].imag = 0.0;
 
-        freq_hz = fdmdv->fsep*( -(COHPSK_NC*ND)/2 - 0.5 + c + 1.0 );
+        /* note non-linear carrier spacing to help PAPR, works v well in conjunction with CLIP */
+
+        freq_hz = fdmdv->fsep*( -(COHPSK_NC*ND)/2 - 0.5 + pow(c + 1.0, 0.98) );
         
        fdmdv->freq[c].real = cosf(2.0*M_PI*freq_hz/COHPSK_FS);
        fdmdv->freq[c].imag = sinf(2.0*M_PI*freq_hz/COHPSK_FS);
        fdmdv->freq_pol[c]  = 2.0*M_PI*freq_hz/COHPSK_FS;
 
-        printf("c: %d %f %f\n",c,freq_hz,fdmdv->freq_pol[c]);
+        //printf("c: %d %f %f\n",c,freq_hz,fdmdv->freq_pol[c]);
         for(i=0; i<COHPSK_NFILTER; i++) {
             coh->rx_filter_memory[c][i].real = 0.0;
             coh->rx_filter_memory[c][i].imag = 0.0;
@@ -616,8 +618,8 @@ int sync_state_machine(struct COHPSK *coh, int sync, int next_sync)
 void cohpsk_mod(struct COHPSK *coh, COMP tx_fdm[], int tx_bits[])
 {
     struct FDMDV *fdmdv = coh->fdmdv;
-    COMP tx_symb[NSYMROWPILOT][COHPSK_NC*ND];
-    COMP tx_onesym[COHPSK_NC*ND];
+    COMP  tx_symb[NSYMROWPILOT][COHPSK_NC*ND];
+    COMP  tx_onesym[COHPSK_NC*ND];
     int  r,c;
 
     bits_to_qpsk_symbols(tx_symb, tx_bits, COHPSK_BITS_PER_FRAME);
@@ -631,6 +633,33 @@ void cohpsk_mod(struct COHPSK *coh, COMP tx_fdm[], int tx_bits[])
 }
 
 
+/*---------------------------------------------------------------------------*\
+                                                       
+  FUNCTION....: cohpsk_clip()       
+  AUTHOR......: David Rowe                           
+  DATE CREATED: May 2015
+
+  Hard clips a cohpsk modulator signal to improve PAPR, CLIP threshold
+  hard coded and will need to be changed if NC*ND does.
+
+\*---------------------------------------------------------------------------*/
+
+void cohpsk_clip(COMP tx_fdm[])
+{
+    COMP  sam;
+    float mag;
+    int   i;
+
+    for(i=0; i<COHPSK_SAMPLES_PER_FRAME; i++) {
+        sam = tx_fdm[i];
+        mag = cabsolute(sam);            
+        if (mag >  COHPSK_CLIP)  {
+            sam = fcmult( COHPSK_CLIP/mag, sam);
+        }
+        tx_fdm[i] = sam;
+    }
+ }
 /*---------------------------------------------------------------------------*\
                                                        
   FUNCTION....: fdm_downconvert_coh   
index c98c580b9bd3b717221e07b5557d693f13f7a2a7..5a8c047440f633371a2ee3ad1c0f6527f087094a 100644 (file)
@@ -38,7 +38,8 @@
 #define COHPSK_NFILTER    (COHPSK_NSYM*COHPSK_M)
 #define COHPSK_EXCESS_BW  0.5                         /* excess BW factor of root nyq filter */
 #define COHPSK_NT         5                           /* number of symbols we estimate timing over */
-
+#define COHPSK_CLIP       6.5                         /* hard clipping for Nc*Nc=14 to reduce PAPR */
 #include "fdmdv_internal.h"
 #include "kiss_fft.h"
 
index 7b16e4f0ad4144025bdd16b912334a98b35de73c..49a0c9cec0645db6f62a29994c73e6f09e1afbd5 100644 (file)
@@ -158,6 +158,7 @@ int main(int argc, char *argv[])
            tx_filter_and_upconvert_coh(&tx_fdm_frame[r*COHPSK_M], COHPSK_NC*ND , tx_onesym, fdmdv->tx_filter_memory, 
                                         fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect);
         }
+        cohpsk_clip(tx_fdm_frame);
 
        /* --------------------------------------------------------*\
                                  Channel