#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
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;
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;
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;
}
}
}
// 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]);
}
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;
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);
//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");
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");
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;
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
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. */
\*---------------------------------------------------------------------------*/
+#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 */
#ifndef __FREEDV__
// This declares a single-precision (float) complex number
+#include <sys/types.h>
#include "comp.h"
#define FREEDV_MODE_1600 0
/* 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);
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);
}