ARM specific optimisations to fdmdv modem, thanks Danilo and mcHF team who tested...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 8 Sep 2016 22:17:11 +0000 (22:17 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 8 Sep 2016 22:17:11 +0000 (22:17 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2850 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/fdmdv.c
codec2-dev/src/fdmdv_internal.h
codec2-dev/src/freedv_api.h
codec2-dev/src/octave.c

index e23bf878d0eac8ce7ddf714663e5472e7bff4bd1..3b3d9fad3ee483ca0c8eec560c5cfeb72248afaf 100644 (file)
 #include <string.h>
 #include <math.h>
 
+#ifdef ARM_MATH_CM4
+  #include "stm32f4xx.h"
+  #include "core_cm4.h"
+  #include "arm_math.h"
+#endif
+
+
 #include "fdmdv_internal.h"
 #include "codec2_fdmdv.h"
 #include "comp_prim.h"
 #include "machdep.h"
 
 static int sync_uw[] = {1,-1,1,-1,1,-1};
-
 #ifdef __EMBEDDED__
 #define printf gdb_stdio_printf
 #endif
 
+#ifndef ARM_MATH_CM4
+  #define SINF(a) sinf(a)
+  #define COSF(a) cosf(a)
+#else
+  #define SINF(a) arm_sin_f32(a)
+  #define COSF(a) arm_cos_f32(a)
+#endif
+
+static const COMP  pi_on_4 = { .70710678118654752439, .70710678118654752439 }; // COSF(PI/4) , SINF(PI/4)
+
+
 /*--------------------------------------------------------------------------* \
 
   FUNCTION....: fdmdv_create
@@ -110,8 +127,8 @@ struct FDMDV * fdmdv_create(int Nc)
            This helped PAPR for a few dB.  We don't need to adjust rx
            phase as DQPSK takes care of that. */
 
-       f->phase_tx[c].real = cosf(2.0*PI*c/(Nc+1));
-       f->phase_tx[c].imag = sinf(2.0*PI*c/(Nc+1));
+       f->phase_tx[c].real = COSF(2.0*PI*c/(Nc+1));
+       f->phase_tx[c].imag = SINF(2.0*PI*c/(Nc+1));
 
        f->phase_rx[c].real = 1.0;
        f->phase_rx[c].imag = 0.0;
@@ -124,12 +141,12 @@ struct FDMDV * fdmdv_create(int Nc)
     f->prev_tx_symbols[Nc].real = 2.0;
 
     fdmdv_set_fsep(f, FSEP);
-    f->freq[Nc].real = cosf(2.0*PI*0.0/FS);
-    f->freq[Nc].imag = sinf(2.0*PI*0.0/FS);
+    f->freq[Nc].real = COSF(2.0*PI*0.0/FS);
+    f->freq[Nc].imag = SINF(2.0*PI*0.0/FS);
     f->freq_pol[Nc]  = 2.0*PI*0.0/FS;
 
-    f->fbb_rect.real     = cosf(2.0*PI*FDMDV_FCENTRE/FS);
-    f->fbb_rect.imag     = sinf(2.0*PI*FDMDV_FCENTRE/FS);
+    f->fbb_rect.real     = COSF(2.0*PI*FDMDV_FCENTRE/FS);
+    f->fbb_rect.imag     = SINF(2.0*PI*FDMDV_FCENTRE/FS);
     f->fbb_pol           = 2.0*PI*FDMDV_FCENTRE/FS;
     f->fbb_phase_tx.real = 1.0;
     f->fbb_phase_tx.imag = 0.0;
@@ -257,15 +274,15 @@ void fdmdv_set_fsep(struct FDMDV *f, float fsep) {
 
     for(c=0; c<f->Nc/2; c++) {
        carrier_freq = (-f->Nc/2 + c)*f->fsep;
-       f->freq[c].real = cosf(2.0*PI*carrier_freq/FS);
-       f->freq[c].imag = sinf(2.0*PI*carrier_freq/FS);
+       f->freq[c].real = COSF(2.0*PI*carrier_freq/FS);
+       f->freq[c].imag = SINF(2.0*PI*carrier_freq/FS);
        f->freq_pol[c]  = 2.0*PI*carrier_freq/FS;
     }
 
     for(c=f->Nc/2; c<f->Nc; c++) {
        carrier_freq = (-f->Nc/2 + c + 1)*f->fsep;
-       f->freq[c].real = cosf(2.0*PI*carrier_freq/FS);
-       f->freq[c].imag = sinf(2.0*PI*carrier_freq/FS);
+       f->freq[c].real = COSF(2.0*PI*carrier_freq/FS);
+       f->freq[c].imag = SINF(2.0*PI*carrier_freq/FS);
        f->freq_pol[c]  = 2.0*PI*carrier_freq/FS;
     }
 }
@@ -678,8 +695,8 @@ void generate_pilot_lut(COMP pilot_lut[], COMP *pilot_freq)
     }
    
     // create complex conjugate since we need this and only this later on 
-
-    for (f=0;f<4*M;f++) {
+    for (f=0;f<4*M;f++)
+    {
         pilot_lut[f] = cconj(pilot_lut[f]);
     }
 
@@ -777,7 +794,10 @@ void lpf_peak_pick(float *foff, float *max, COMP pilot_baseband[],
 
 float rx_est_freq_offset(struct FDMDV *f, COMP rx_fdm[], int nin, int do_fft)
 {
-    int  i,j;
+    int  i;
+#ifndef ARM_MATH_CM4
+    int j;
+#endif
     COMP pilot[M+M/P];
     COMP prev_pilot[M+M/P];
     float foff, foff1, foff2;
@@ -854,8 +874,8 @@ void fdmdv_freq_shift(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff,
     float mag;
     int   i;
 
-    foff_rect.real = cosf(2.0*PI*foff/FS);
-    foff_rect.imag = sinf(2.0*PI*foff/FS);
+    foff_rect.real = COSF(2.0*PI*foff/FS);
+    foff_rect.imag = SINF(2.0*PI*foff/FS);
     for(i=0; i<nin; i++) {
        *foff_phase_rect = cmult(*foff_phase_rect, foff_rect);
        rx_fdm_fcorr[i] = cmult(rx_fdm[i], *foff_phase_rect);
@@ -1079,8 +1099,8 @@ void down_convert_and_rx_filter(COMP rx_filt[NC+1][P+1], int Nc, COMP rx_fdm[],
 
         //PROFILE_SAMPLE(windback_start);
         windback_phase           = -freq_pol[c]*NFILTER;
-        windback_phase_rect.real = cosf(windback_phase);
-        windback_phase_rect.imag = sinf(windback_phase);
+        windback_phase_rect.real = COSF(windback_phase);
+        windback_phase_rect.imag = SINF(windback_phase);
         phase_rx[c]              = cmult(phase_rx[c],windback_phase_rect);
         //PROFILE_SAMPLE_AND_LOG(downconvert_start, windback_start, "        windback");
 
@@ -1112,9 +1132,9 @@ void down_convert_and_rx_filter(COMP rx_filt[NC+1][P+1], int Nc, COMP rx_fdm[],
            for(m=0; m<NFILTER; m++)
                rx_filt[c][k] = cadd(rx_filt[c][k], fcmult(gt_alpha5_root[m], rx_baseband[st+i+m]));
            #else
-           // rx_filt[c][k].real = fir_filter(&rx_baseband[st+i].real, (float*)gt_alpha5_root, dec_rate);
-           // rx_filt[c][k].imag = fir_filter(&rx_baseband[st+i].imag, (float*)gt_alpha5_root, dec_rate);
-               fir_filter2(&rx_filt[c][k].real,&rx_baseband[st+i].real, (float*)gt_alpha5_root, dec_rate);
+            // rx_filt[c][k].real = fir_filter(&rx_baseband[st+i].real, (float*)gt_alpha5_root, dec_rate);
+            // rx_filt[c][k].imag = fir_filter(&rx_baseband[st+i].imag, (float*)gt_alpha5_root, dec_rate);
+           fir_filter2(&rx_filt[c][k].real,&rx_baseband[st+i].real, (float*)gt_alpha5_root, dec_rate);
            #endif
         }
         //PROFILE_SAMPLE_AND_LOG2(filter_start, "        filter");
@@ -1186,8 +1206,8 @@ float rx_est_timing(COMP rx_symbols[],
        out single DFT at frequency 2*pi/P */
 
     x.real = 0.0; x.imag = 0.0;
-    freq.real = cosf(2*PI/P);
-    freq.imag = sinf(2*PI/P);
+    freq.real = COSF(2*PI/P);
+    freq.imag = SINF(2*PI/P);
     phase.real = 1.0;
     phase.imag = 0.0;
 
@@ -1244,13 +1264,10 @@ float qpsk_to_bits(int rx_bits[], int *sync_bit, int Nc, COMP phase_difference[]
                    COMP rx_symbols[], int old_qpsk_mapping)
 {
     int   c;
-    COMP  pi_on_4;
     COMP  d;
     int   msb=0, lsb=0;
     float ferr, norm;
 
-    pi_on_4.real = cosf(PI/4.0);
-    pi_on_4.imag = sinf(PI/4.0);
 
     /* Extra 45 degree clockwise lets us use real and imag axis as
        decision boundaries. "norm" makes sure the phase subtraction
@@ -1327,11 +1344,8 @@ void snr_update(float sig_est[], float noise_est[], int Nc, COMP phase_differenc
     float s[NC+1];
     COMP  refl_symbols[NC+1];
     float n[NC+1];
-    COMP  pi_on_4;
     int   c;
 
-    pi_on_4.real = cosf(PI/4.0);
-    pi_on_4.imag = sinf(PI/4.0);
 
     /* mag of each symbol is distance from origin, this gives us a
        vector of mags, one for each carrier. */
index 86f3e3abc4989e39495e66fe8dd3359c19c64bf1..317a3b9d2c830f285c63a16e9bb288ced69a5d94 100644 (file)
@@ -39,7 +39,9 @@
 
 \*---------------------------------------------------------------------------*/
 
+#ifndef PI
 #define PI             3.141592654
+#endif
 #define FS                    8000  /* sample rate in Hz                                                    */
 #define T                 (1.0/FS)  /* sample period in seconds                                             */
 #define RS                      50  /* symbol rate in Hz                                                    */
index 593e8621b525c0085974ec0a440740ee49398d4c..d5a50dee5691ca6d5109732f3f3f6800380df662 100644 (file)
@@ -35,6 +35,7 @@
 #ifndef __FREEDV__
 
 // This declares a single-precision (float) complex number
+#include <sys/types.h>
 #include "comp.h"
 
 #define FREEDV_MODE_1600        0
@@ -56,51 +57,51 @@ typedef void (*freedv_calback_error_pattern)
 /* Protocol bits are packed MSB-first */
 /* Called when a frame containing protocol data is decoded */
 typedef void (*freedv_callback_protorx)(void *, char *);
-/* Called when a frame containing protocol data is to be sent */\r
-typedef void (*freedv_callback_prototx)(void *, char *);\r
-\r
-/* Data packet callbacks */\r
-/* Called when a packet has been received */\r
-typedef void (*freedv_callback_datarx)(void *, unsigned char *packet, size_t size);\r
-/* Called when a new packet can be send */\r
-typedef void (*freedv_callback_datatx)(void *, unsigned char *packet, size_t *size);\r
-\r
-\r
-// FreeDV API functions:\r
-// open, close\r
-struct freedv *freedv_open(int mode);\r
+/* Called when a frame containing protocol data is to be sent */
+typedef void (*freedv_callback_prototx)(void *, char *);
+
+/* Data packet callbacks */
+/* Called when a packet has been received */
+typedef void (*freedv_callback_datarx)(void *, unsigned char *packet, size_t size);
+/* Called when a new packet can be send */
+typedef void (*freedv_callback_datatx)(void *, unsigned char *packet, size_t *size);
+
+
+// FreeDV API functions:
+// open, close
+struct freedv *freedv_open(int mode);
 void freedv_close   (struct freedv *freedv);
 // Transmit
-void freedv_tx      (struct freedv *freedv, short mod_out[], short speech_in[]);\r
-void freedv_comptx  (struct freedv *freedv, COMP  mod_out[], short speech_in[]);\r
-void freedv_codectx (struct freedv *f, short mod_out[], unsigned char *packed_codec_bits);\r
-void freedv_datatx  (struct freedv *f, short mod_out[]);\r
-int  freedv_data_ntxframes (struct freedv *freedv);\r
-// Receive\r
-int freedv_nin      (struct freedv *freedv);\r
-int freedv_rx       (struct freedv *freedv, short speech_out[], short demod_in[]);\r
+void freedv_tx      (struct freedv *freedv, short mod_out[], short speech_in[]);
+void freedv_comptx  (struct freedv *freedv, COMP  mod_out[], short speech_in[]);
+void freedv_codectx (struct freedv *f, short mod_out[], unsigned char *packed_codec_bits);
+void freedv_datatx  (struct freedv *f, short mod_out[]);
+int  freedv_data_ntxframes (struct freedv *freedv);
+// Receive
+int freedv_nin      (struct freedv *freedv);
+int freedv_rx       (struct freedv *freedv, short speech_out[], short demod_in[]);
 int freedv_floatrx  (struct freedv *freedv, short speech_out[], float demod_in[]);
 int freedv_comprx   (struct freedv *freedv, short speech_out[], COMP  demod_in[]);
 int freedv_codecrx  (struct freedv *freedv, unsigned char *packed_codec_bits, short demod_in[]);
-// Set parameters\r
-void freedv_set_callback_txt            (struct freedv *freedv, freedv_callback_rx rx, freedv_callback_tx tx, void *callback_state);\r
-void freedv_set_callback_protocol       (struct freedv *freedv, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state);\r
-void freedv_set_callback_data         (struct freedv *freedv, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state);\r
-void freedv_set_test_frames                        (struct freedv *freedv, int test_frames);\r
-void freedv_set_smooth_symbols             (struct freedv *freedv, int smooth_symbols);\r
-void freedv_set_squelch_en                         (struct freedv *freedv, int squelch_en);\r
+// Set parameters
+void freedv_set_callback_txt            (struct freedv *freedv, freedv_callback_rx rx, freedv_callback_tx tx, void *callback_state);
+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_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);
 void freedv_set_clip                   (struct freedv *freedv, int val);
 void freedv_set_total_bit_errors       (struct freedv *freedv, int val);
-void freedv_set_total_bits              (struct freedv *freedv, int val);\r
-void freedv_set_callback_error_pattern  (struct freedv *freedv, freedv_calback_error_pattern cb, void *state);\r
-void freedv_set_varicode_code_num       (struct freedv *freedv, int val);\r
+void freedv_set_total_bits              (struct freedv *freedv, int val);
+void freedv_set_callback_error_pattern  (struct freedv *freedv, freedv_calback_error_pattern cb, void *state);
+void freedv_set_varicode_code_num       (struct freedv *freedv, int val);
 void freedv_set_data_header             (struct freedv *freedv, unsigned char *header);
-int freedv_set_alt_modem_samp_rate      (struct freedv *freedv, int samp_rate);\r
-\r
-// Get parameters\r
+int freedv_set_alt_modem_samp_rate      (struct freedv *freedv, int samp_rate);
+
+// Get parameters
 struct MODEM_STATS;
-int freedv_get_version(void);\r
+int freedv_get_version(void);
 int freedv_get_mode                 (struct freedv *freedv);
 void freedv_get_modem_stats         (struct freedv *freedv, int *sync, float *snr_est);
 void freedv_get_modem_extended_stats(struct freedv *freedv, struct MODEM_STATS *stats);
index e73ae1d1cdc6353b1b1d74e3c8ddd409e72e27c2..b22598965d9c85b66cfba4753e84baf147eee6d9 100644 (file)
 
   You should have received a copy of the GNU Lesser General Public License
   along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
+ */
 
 #include <stdio.h>
+#include <stdarg.h>
+
 #include "octave.h"
 
+#ifdef ARM_MATH_CM4
+#include "Trace.h"
+#endif
+
+#define OCTAVE_BUFSIZE 2048
+
+
+void flush_buffer(FILE* f, char* buffer,size_t* buf_idx_ptr)
+{
+#ifdef ARM_MATH_CM4
+    trace_write(buffer,*buf_idx_ptr);
+#else
+    fwrite(buffer,*buf_idx_ptr,1,f);
+#endif
+    *buf_idx_ptr = 0;
+}
+
+void handle_buffer(FILE* f, char* buffer,const size_t max_buf, size_t* buf_idx_ptr, size_t l)
+{
+    *buf_idx_ptr += l;
+    if (*buf_idx_ptr > max_buf - 64)
+    {
+        flush_buffer(f, buffer,buf_idx_ptr);
+    }
+}
+
+signed int printf_buffer(FILE* f, char* buffer,const size_t max_buf, size_t* buf_idx_ptr, const char *pFormat, ...)
+{
+    va_list    ap;
+    signed int rc;
+
+    va_start(ap, pFormat);
+    rc = vsnprintf(&buffer[*buf_idx_ptr], max_buf - *buf_idx_ptr, pFormat, ap);
+    va_end(ap);
+    if (rc>0)
+    {
+        handle_buffer(f, buffer,max_buf,buf_idx_ptr,rc);
+    }
+    return rc;
+}
+
+
+signed int printf_header(FILE* f, char* buffer,const size_t max_buf, size_t* buf_idx_ptr, const char *name, const char *dtype, int rows, int cols, int isFloat)
+{
+#ifdef ARM_MATH_CM4
+    printf_buffer(f, buffer, OCTAVE_BUFSIZE, buf_idx_ptr, "# hex: %s\n", isFloat?"true":"false");
+#endif    
+    printf_buffer(f, buffer, OCTAVE_BUFSIZE, buf_idx_ptr, "# name: %s\n", name);
+    printf_buffer(f, buffer, OCTAVE_BUFSIZE, buf_idx_ptr, "# type: %s\n",dtype);
+    printf_buffer(f, buffer, OCTAVE_BUFSIZE, buf_idx_ptr, "# rows: %d\n", rows);
+    printf_buffer(f, buffer, OCTAVE_BUFSIZE, buf_idx_ptr, "# columns: %d\n", cols);
+}
 void octave_save_int(FILE *f, char name[], int data[], int rows, int cols)
 {
     int r,c;
+    char buffer[OCTAVE_BUFSIZE];
+    size_t buf_idx = 0;
 
-    fprintf(f, "# name: %s\n", name);
-    fprintf(f, "# type: matrix\n");
-    fprintf(f, "# rows: %d\n", rows);
-    fprintf(f, "# columns: %d\n", cols);
+    printf_header(f, buffer, OCTAVE_BUFSIZE, &buf_idx, name, "matrix", rows, cols, 0);
 
     for(r=0; r<rows; r++) {
-       for(c=0; c<cols; c++)
-           fprintf(f, " %d", data[r*cols+c]);
-       fprintf(f, "\n");
+        for(c=0; c<cols; c++)
+            printf_buffer(f, buffer, OCTAVE_BUFSIZE, &buf_idx, " %d", data[r*cols+c]);
+        printf_buffer(f, buffer, OCTAVE_BUFSIZE, &buf_idx, "\n");
     }
 
-    fprintf(f, "\n\n");
+    printf_buffer(f, buffer, OCTAVE_BUFSIZE, &buf_idx, "\n\n");
+    flush_buffer(f, buffer, &buf_idx);
 }
 
 void octave_save_float(FILE *f, char name[], float data[], int rows, int cols, int col_len)
 {
     int r,c;
+    char buffer[OCTAVE_BUFSIZE];
+    size_t buf_idx = 0;
 
-    fprintf(f, "# name: %s\n", name);
-    fprintf(f, "# type: matrix\n");
-    fprintf(f, "# rows: %d\n", rows);
-    fprintf(f, "# columns: %d\n", cols);
+    printf_header(f, buffer, OCTAVE_BUFSIZE, &buf_idx, name, "matrix", rows, cols, 1);
 
     for(r=0; r<rows; r++) {
-       for(c=0; c<cols; c++)
-           fprintf(f, " %f", data[r*col_len+c]);
-       fprintf(f, "\n");
+        for(c=0; c<cols; c++)
+            printf_buffer(f, buffer, OCTAVE_BUFSIZE, &buf_idx, " %f", data[r*col_len+c]);
+        printf_buffer(f, buffer, OCTAVE_BUFSIZE, &buf_idx, "\n");
     }
 
-    fprintf(f, "\n\n");
+    printf_buffer(f, buffer, OCTAVE_BUFSIZE, &buf_idx, "\n\n");
+    flush_buffer(f, buffer, &buf_idx);
 }
 
+
 void octave_save_complex(FILE *f, char name[], COMP data[], int rows, int cols, int col_len)
 {
     int r,c;
+    char buffer[OCTAVE_BUFSIZE];
+    size_t buf_idx = 0;
+
 
-    fprintf(f, "# name: %s\n", name);
-    fprintf(f, "# type: complex matrix\n");
-    fprintf(f, "# rows: %d\n", rows);
-    fprintf(f, "# columns: %d\n", cols);
+    printf_header(f, buffer, OCTAVE_BUFSIZE, &buf_idx, name, "complex matrix", rows, cols, 1);
 
     for(r=0; r<rows; r++) {
-       for(c=0; c<cols; c++)
-           fprintf(f, " (%f,%f)", data[r*col_len+c].real, data[r*col_len+c].imag);
-       fprintf(f, "\n");
-    }
 
-    fprintf(f, "\n\n");
+        for(c=0; c<cols; c++)
+        {
+            printf_buffer(f, buffer, OCTAVE_BUFSIZE, &buf_idx, " (%f,%f)", data[r*col_len+c].real, data[r*col_len+c].imag);
+        }
+        printf_buffer(f, buffer, OCTAVE_BUFSIZE, &buf_idx, "\n");
+    }
+    printf_buffer(f, buffer, OCTAVE_BUFSIZE, &buf_idx, "\n\n");
+    flush_buffer(f, buffer, &buf_idx);
 }