endfunction
-function check(a, b, test_name, tol, its_an_angle = 0)
+function pass = check(a, b, test_name, tol, its_an_angle = 0)
global passes;
global fails;
if e < tol
printf("OK\n");
+ pass = true;
passes++;
else
printf("FAIL (%f)\n",e);
+ pass = false;
fails++;
end
endfunction
-function check_no_abs(a, b, test_name)
+function pass = check_no_abs(a, b, test_name)
global passes;
global fails;
e = sum(sum(a - b)/ll);
if e < tol
+ pass = true;
printf("OK\n");
passes++;
else
+ pass = false;
printf("FAIL (%f)\n",e);
fails++;
end
% Octave script for comparing Octave and C versions of OFDZM modem
% ------------------------------------------------------------------
+1;
-Nframes = 30;
-sample_clock_offset_ppm = 100;
-foff_hz = 0.5;
+function pass = run_ofdm_test(Nframes,sample_clock_offset_ppm,foff_hz)
+ %Nframes = 30;
+ %sample_clock_offset_ppm = 100;
+ %foff_hz = 5;
-more off; format;
-ofdm_lib;
-autotest;
+ more off; format;
+ ofdm_lib;
+ autotest;
-% ---------------------------------------------------------------------
-% Run Octave version
-% ---------------------------------------------------------------------
+ % ---------------------------------------------------------------------
+ % Run Octave version
+ % ---------------------------------------------------------------------
-Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 16; Ns = 8;
-states = ofdm_init(bps, Rs, Tcp, Ns, Nc);
-ofdm_load_const;
+ Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 16; Ns = 8;
+ states = ofdm_init(bps, Rs, Tcp, Ns, Nc);
+ ofdm_load_const;
-rand('seed',1);
-tx_bits = round(rand(1,Nbitsperframe));
+ rand('seed',1);
+ tx_bits = round(rand(1,Nbitsperframe));
-% Run tx loop
+ % Run tx loop
-tx_bits_log = []; tx_log = [];
-for f=1:Nframes
- tx_bits_log = [tx_bits_log tx_bits];
- tx_log = [tx_log ofdm_mod(states, tx_bits)];
-end
-
-% Channel simulation ----------------------------------------------
+ tx_bits_log = []; tx_log = [];
+ for f=1:Nframes
+ tx_bits_log = [tx_bits_log tx_bits];
+ tx_log = [tx_log ofdm_mod(states, tx_bits)];
+ end
-rx_log = sample_clock_offset(tx_log, sample_clock_offset_ppm);
-rx_log = freq_shift(rx_log, foff_hz, Fs);
+ % Channel simulation ----------------------------------------------
-% Rx ---------------------------------------------------------------
+ rx_log = sample_clock_offset(tx_log, sample_clock_offset_ppm);
+ rx_log = freq_shift(rx_log, foff_hz, Fs);
-% Init rx with ideal timing so we can test with timing estimation disabled
+ % Rx ---------------------------------------------------------------
-Nsam = length(rx_log);
-prx = 1;
-nin = Nsamperframe+2*(M+Ncp);
-states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx_log(prx:nin);
-prx += nin;
+ % Init rx with ideal timing so we can test with timing estimation disabled
-rxbuf_log = []; rxbuf_in_log = []; rx_sym_log = []; foff_hz_log = [];
-timing_est_log = []; sample_point_log = [];
-phase_est_pilot_log = []; rx_amp_log = [];
-rx_np_log = []; rx_bits_log = [];
+ Nsam = length(rx_log);
+ prx = 1;
+ nin = Nsamperframe+2*(M+Ncp);
+ states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx_log(prx:nin);
+ prx += nin;
-states.timing_en = 1;
-states.foff_est_en = 1;
-states.phase_est_en = 1;
+ rxbuf_log = []; rxbuf_in_log = []; rx_sym_log = []; foff_hz_log = [];
+ timing_est_log = []; sample_point_log = [];
+ phase_est_pilot_log = []; rx_amp_log = [];
+ rx_np_log = []; rx_bits_log = [];
-if states.timing_en == 0
- % manually set ideal timing instant
- states.sample_point = Ncp;
-end
+ states.timing_en = 1;
+ states.foff_est_en = 1;
+ states.phase_est_en = 1;
-for f=1:Nframes
-
- % insert samples at end of buffer, set to zero if no samples
- % available to disable phase estimation on future pilots on last
- % frame of simulation
-
- nin = states.nin;
- lnew = min(Nsam-prx+1,nin);
- rxbuf_in = zeros(1,nin);
- %printf("nin: %d prx: %d lnew: %d\n", nin, prx, lnew);
- if lnew
- rxbuf_in(1:lnew) = rx_log(prx:prx+lnew-1);
+ if states.timing_en == 0
+ % manually set ideal timing instant
+ states.sample_point = Ncp;
end
- prx += lnew;
-
- [rx_bits states aphase_est_pilot_log arx_np arx_amp] = ofdm_demod(states, rxbuf_in);
-
- % log some states for comparison to C
-
- rxbuf_in_log = [rxbuf_in_log rxbuf_in];
- rxbuf_log = [rxbuf_log states.rxbuf];
- rx_sym_log = [rx_sym_log; states.rx_sym];
- phase_est_pilot_log = [phase_est_pilot_log; aphase_est_pilot_log];
- rx_amp_log = [rx_amp_log arx_amp];
- foff_hz_log = [foff_hz_log; states.foff_est_hz];
- timing_est_log = [timing_est_log; states.timing_est];
- sample_point_log = [sample_point_log; states.sample_point];
- rx_np_log = [rx_np_log arx_np];
- rx_bits_log = [rx_bits_log rx_bits];
+
+ for f=1:Nframes
+
+ % insert samples at end of buffer, set to zero if no samples
+ % available to disable phase estimation on future pilots on last
+ % frame of simulation
-end
+ nin = states.nin;
+ lnew = min(Nsam-prx+1,nin);
+ rxbuf_in = zeros(1,nin);
+ %printf("nin: %d prx: %d lnew: %d\n", nin, prx, lnew);
+ if lnew
+ rxbuf_in(1:lnew) = rx_log(prx:prx+lnew-1);
+ end
+ prx += lnew;
+
+ [rx_bits states aphase_est_pilot_log arx_np arx_amp] = ofdm_demod(states, rxbuf_in);
+
+ % log some states for comparison to C
+
+ rxbuf_in_log = [rxbuf_in_log rxbuf_in];
+ rxbuf_log = [rxbuf_log states.rxbuf];
+ rx_sym_log = [rx_sym_log; states.rx_sym];
+ phase_est_pilot_log = [phase_est_pilot_log; aphase_est_pilot_log];
+ rx_amp_log = [rx_amp_log arx_amp];
+ foff_hz_log = [foff_hz_log; states.foff_est_hz];
+ timing_est_log = [timing_est_log; states.timing_est];
+ sample_point_log = [sample_point_log; states.sample_point];
+ rx_np_log = [rx_np_log arx_np];
+ rx_bits_log = [rx_bits_log rx_bits];
+
+ end
-% ---------------------------------------------------------------------
-% Run C version and plot Octave and C states and differences
-% ---------------------------------------------------------------------
+ % ---------------------------------------------------------------------
+ % Run C version and plot Octave and C states and differences
+ % ---------------------------------------------------------------------
-% Override default path by setting path_to_tofdm = "/your/path/to/tofdm"
+ % Override default path by setting path_to_tofdm = "/your/path/to/tofdm"
-if exist("path_to_tofdm", "var") == 0
- path_to_tofdm = "../build_linux/unittest/tofdm";
-end
-system(path_to_tofdm);
+ if exist("path_to_tofdm", "var") == 0
+ path_to_tofdm = "../build_linux/unittest/tofdm";
+ end
+ system(path_to_tofdm);
-load tofdm_out.txt;
+ load tofdm_out.txt;
+ % Generated with modem probe thing
+ load ofdm_test.txt;
-fg = 1;
-figure(fg++); clf; plot(rx_np_log,'+'); title('Octave Scatter Diagram'); axis([-1.5 1.5 -1.5 1.5]);
-figure(fg++); clf; plot(rx_np_log_c,'+'); title('C Scatter Diagram'); axis([-1.5 1.5 -1.5 1.5]);
+ fg = 1;
+ figure(fg++); clf; plot(rx_np_log,'+'); title('Octave Scatter Diagram'); axis([-1.5 1.5 -1.5 1.5]);
+ figure(fg++); clf; plot(rx_np_log_c,'+'); title('C Scatter Diagram'); axis([-1.5 1.5 -1.5 1.5]);
-stem_sig_and_error(fg++, 111, tx_bits_log_c, tx_bits_log - tx_bits_log_c, 'tx bits', [1 length(tx_bits_log) -1.5 1.5])
+ stem_sig_and_error(fg++, 111, tx_bits_log_c, tx_bits_log - tx_bits_log_c, 'tx bits', [1 length(tx_bits_log) -1.5 1.5])
-stem_sig_and_error(fg, 211, real(tx_log_c), real(tx_log - tx_log_c), 'tx re', [1 length(tx_log_c) -0.1 0.1])
-stem_sig_and_error(fg++, 212, imag(tx_log_c), imag(tx_log - tx_log_c), 'tx im', [1 length(tx_log_c) -0.1 0.1])
+ stem_sig_and_error(fg, 211, real(tx_log_c), real(tx_log - tx_log_c), 'tx re', [1 length(tx_log_c) -0.1 0.1])
+ stem_sig_and_error(fg++, 212, imag(tx_log_c), imag(tx_log - tx_log_c), 'tx im', [1 length(tx_log_c) -0.1 0.1])
-stem_sig_and_error(fg, 211, real(rx_log_c), real(rx_log - rx_log_c), 'rx re', [1 length(rx_log_c) -0.1 0.1])
-stem_sig_and_error(fg++, 212, imag(rx_log_c), imag(rx_log - rx_log_c), 'rx im', [1 length(rx_log_c) -0.1 0.1])
+ stem_sig_and_error(fg, 211, real(rx_log_c), real(rx_log - rx_log_c), 'rx re', [1 length(rx_log_c) -0.1 0.1])
+ stem_sig_and_error(fg++, 212, imag(rx_log_c), imag(rx_log - rx_log_c), 'rx im', [1 length(rx_log_c) -0.1 0.1])
-stem_sig_and_error(fg, 211, real(rxbuf_in_log_c), real(rxbuf_in_log - rxbuf_in_log_c), 'rxbuf in re', [1 length(rxbuf_in_log_c) -0.1 0.1])
-stem_sig_and_error(fg++, 212, imag(rxbuf_in_log_c), imag(rxbuf_in_log - rxbuf_in_log_c), 'rxbuf in im', [1 length(rxbuf_in_log_c) -0.1 0.1])
+ stem_sig_and_error(fg, 211, real(rxbuf_in_log_c), real(rxbuf_in_log - rxbuf_in_log_c), 'rxbuf in re', [1 length(rxbuf_in_log_c) -0.1 0.1])
+ stem_sig_and_error(fg++, 212, imag(rxbuf_in_log_c), imag(rxbuf_in_log - rxbuf_in_log_c), 'rxbuf in im', [1 length(rxbuf_in_log_c) -0.1 0.1])
-stem_sig_and_error(fg, 211, real(rxbuf_log_c), real(rxbuf_log - rxbuf_log_c), 'rxbuf re', [1 length(rxbuf_log_c) -0.1 0.1])
-stem_sig_and_error(fg++, 212, imag(rxbuf_log_c), imag(rxbuf_log - rxbuf_log_c), 'rxbuf im', [1 length(rxbuf_log_c) -0.1 0.1])
+ stem_sig_and_error(fg, 211, real(rxbuf_log_c), real(rxbuf_log - rxbuf_log_c), 'rxbuf re', [1 length(rxbuf_log_c) -0.1 0.1])
+ stem_sig_and_error(fg++, 212, imag(rxbuf_log_c), imag(rxbuf_log - rxbuf_log_c), 'rxbuf im', [1 length(rxbuf_log_c) -0.1 0.1])
-stem_sig_and_error(fg, 211, real(rx_sym_log_c), real(rx_sym_log - rx_sym_log_c), 'rx sym re', [1 length(rx_sym_log_c) -1.5 1.5])
-stem_sig_and_error(fg++, 212, imag(rx_sym_log_c), imag(rx_sym_log - rx_sym_log_c), 'rx sym im', [1 length(rx_sym_log_c) -1.5 1.5])
+ stem_sig_and_error(fg, 211, real(rx_sym_log_c), real(rx_sym_log - rx_sym_log_c), 'rx sym re', [1 length(rx_sym_log_c) -1.5 1.5])
+ stem_sig_and_error(fg++, 212, imag(rx_sym_log_c), imag(rx_sym_log - rx_sym_log_c), 'rx sym im', [1 length(rx_sym_log_c) -1.5 1.5])
-% for angles pi and -pi are the same
+ % for angles pi and -pi are the same
-d = phase_est_pilot_log - phase_est_pilot_log_c; d = angle(exp(j*d));
+ d = phase_est_pilot_log - phase_est_pilot_log_c; d = angle(exp(j*d));
-stem_sig_and_error(fg, 211, phase_est_pilot_log_c, d, 'phase est pilot', [1 length(phase_est_pilot_log_c) -1.5 1.5])
-stem_sig_and_error(fg++, 212, rx_amp_log_c, rx_amp_log - rx_amp_log_c, 'rx amp', [1 length(rx_amp_log_c) -1.5 1.5])
+ stem_sig_and_error(fg, 211, phase_est_pilot_log_c, d, 'phase est pilot', [1 length(phase_est_pilot_log_c) -1.5 1.5])
+ stem_sig_and_error(fg++, 212, rx_amp_log_c, rx_amp_log - rx_amp_log_c, 'rx amp', [1 length(rx_amp_log_c) -1.5 1.5])
-stem_sig_and_error(fg++, 111, foff_hz_log_c, (foff_hz_log - foff_hz_log_c), 'foff hz', [1 length(foff_hz_log_c) -1.5 1.5])
+ stem_sig_and_error(fg++, 111, foff_hz_log_c, (foff_hz_log - foff_hz_log_c), 'foff hz', [1 length(foff_hz_log_c) -1.5 1.5])
-stem_sig_and_error(fg, 211, timing_est_log_c, (timing_est_log - timing_est_log_c), 'timing est', [1 length(timing_est_log_c) -1.5 1.5])
-stem_sig_and_error(fg++, 212, sample_point_log_c, (sample_point_log - sample_point_log_c), 'sample point', [1 length(sample_point_log_c) -1.5 1.5])
+ stem_sig_and_error(fg, 211, timing_est_log_c, (timing_est_log - timing_est_log_c), 'timing est', [1 length(timing_est_log_c) -1.5 1.5])
+ stem_sig_and_error(fg++, 212, sample_point_log_c, (sample_point_log - sample_point_log_c), 'sample point', [1 length(sample_point_log_c) -1.5 1.5])
-stem_sig_and_error(fg++, 111, rx_bits_log_c, rx_bits_log - rx_bits_log_c, 'rx bits', [1 length(rx_bits_log) -1.5 1.5])
+ stem_sig_and_error(fg++, 111, rx_bits_log_c, rx_bits_log - rx_bits_log_c, 'rx bits', [1 length(rx_bits_log) -1.5 1.5])
-% Run through checklist -----------------------------
+ % Run through checklist -----------------------------
+ pass = true;
+ pass = check_no_abs(W, W_c, 'W') && pass;
+ pass = check(tx_bits_log, tx_bits_log_c, 'tx_bits') && pass;
+ pass = check(tx_log, tx_log_c, 'tx') && pass;
+ pass = check(rx_log, rx_log_c, 'rx') && pass;
+ pass = check(rxbuf_in_log, rxbuf_in_log_c, 'rxbuf in') && pass;
+ pass = check(rxbuf_log, rxbuf_log_c, 'rxbuf') && pass;
+ pass = check(rx_sym_log, rx_sym_log_c, 'rx_sym') && pass;
+ pass = check(phase_est_pilot_log, phase_est_pilot_log_c, 'phase_est_pilot', tol=1E-3, its_an_angle=1) && pass;
+ pass = check(rx_amp_log, rx_amp_log_c, 'rx_amp') && pass;
+ pass = check(timing_est_log, timing_est_log_c', 'timing_est') && pass;
+ pass = check(sample_point_log, sample_point_log_c, 'sample_point') && pass;
+ pass = check(foff_hz_log, foff_hz_log_c', 'foff_est_hz') && pass;
+ pass = check(rx_bits_log, rx_bits_log_c, 'rx_bits') && pass;
+
-check_no_abs(W, W_c, 'W');
-check(tx_bits_log, tx_bits_log_c, 'tx_bits');
-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_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');
-check(foff_hz_log, foff_hz_log_c, 'foff_est_hz');
-check(rx_bits_log, rx_bits_log_c, 'rx_bits');
+end
+run_ofdm_test(30,100,.1)
\ No newline at end of file
void ofdm_mod(struct OFDM *, COMP *, const int *);
void ofdm_demod(struct OFDM *, int *, COMP *);
int ofdm_get_nin(struct OFDM *);
-int ofdm_get_samples_per_frame(void);
-int ofdm_get_max_samples_per_frame(void);
+int ofdm_get_samples_per_frame(struct OFDM *ofdm);
+int ofdm_get_max_samples_per_frame(struct OFDM *ofdm);
/* option setters */
}
+
void modem_probe_samp_i_int(char * tracename,int32_t samp[],size_t cnt){
probe_trace_info *pti;
datlink *ndat;
#define __MODEMPROBE_H
#include <stdint.h>
#include <stdlib.h>
+#include <complex.h>
#include "comp.h"
-
#ifdef MODEMPROBE_ENABLE
/* Internal functions */
modem_probe_samp_c_int(tracename,samp,cnt);
}
+/*
+ * Save some number of complex samples to a named trace
+ * char *tracename - name of trace being saved to
+ * float complex samp[] - int samples
+ * size_t cnt - how many samples to save
+ */
+static inline void modem_probe_samp_cft(char *tracename,complex float samp[],size_t cnt){
+ modem_probe_samp_c_int(tracename,(COMP*)samp,cnt);
+}
+
#else
static inline void modem_probe_init(char *modname,char *runname){
return;
}
+static inline void modem_probe_samp_cft(char *name,complex float samp[],size_t cnt){
+ return;
+}
+
#endif
#endif
#include "ofdm_internal.h"
#include "codec2_ofdm.h"
#include "kiss_fft.h"
+#include "modem_probe.h"
/* Concrete definition of 700D parameters */
-const struct OFDM_CONFIG OFDM_CONFIG_700D_C =
-{.a = 0};
+const struct OFDM_CONFIG OFDM_CONFIG_700D_C = {
+ .Nc = 16,
+ .Ts = -1,
+ .Rs = -1,
+ .Fs = 8000,
+ .bps = 2,
+ .Tcp = -1,
+ .Ns = 8,
+ .M = 144,
+ .Ncp = 16,
+ .FtWindowWidth = 11,
+ .BitsPerFrame = 224,
+ .SampsPerFrame = 1280,
+ .SampsPerFrameMax = 1320,
+ .RxBufSize = 4320,
+ .RowsPerFrame = 7
+};
/* Pointer to 700D config */
const struct OFDM_CONFIG * OFDM_CONFIG_700D = &OFDM_CONFIG_700D_C;
static void idft(struct OFDM *ofdm, complex float *result, complex float *vector) {
int row, col;
+ int Nc = ofdm->config.Nc;
+ int M = ofdm->config.M;
- for (row = 0; row < OFDM_M; row++) {
+ for (row = 0; row < M; row++) {
result[row] = 0.0f + 0.0f * I;
- for (col = 0; col < (OFDM_NC + 2); col++) {
- result[row] = result[row] + (vector[col] * (ofdm->W[col][row] / (float) OFDM_M)); /* complex result */
+ for (col = 0; col < (Nc + 2); col++) {
+ result[row] = result[row] + (vector[col] * (ofdm->W[col][row] / (float) M)); /* complex result */
}
}
}
static void dft(struct OFDM *ofdm, complex float *result, complex float *vector) {
int row, col;
+ int Nc = ofdm->config.Nc;
+ int M = ofdm->config.M;
- for (col = 0; col < (OFDM_NC + 2); col++) {
+ for (col = 0; col < (Nc + 2); col++) {
result[col] = 0.0f + 0.0f * I;
- for (row = 0; row < OFDM_M; row++) {
+ for (row = 0; row < M; row++) {
result[col] = result[col] + (vector[row] * conjf(ofdm->W[col][row])); /* complex result */
}
}
static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length) {
complex float csam;
- int Ncorr = length - (OFDM_SAMPLESPERFRAME + (OFDM_M + OFDM_NCP));
- int Fs = OFDM_FS;
- int SFrame = OFDM_SAMPLESPERFRAME;
+ int Fs = ofdm->config.Fs;
+ int Rs = ofdm->config.Rs;
+ int Bps = ofdm->config.bps;
+ int Nc = ofdm->config.Nc;
+ int M = ofdm->config.M;
+ int Ncp = ofdm->config.Ncp;
+ int Ns = ofdm->config.Ns;
+ int RowsPerFrame = ofdm->config.RowsPerFrame;
+ int SampsPerFrame = ofdm->config.SampsPerFrame;
+ int Fcenter = ofdm->config.Fcenter;
+ int Ncorr = length - (SampsPerFrame + (M + Ncp));
+
+ int SFrame = SampsPerFrame;
float corr[Ncorr];
+ int NPSamp = M + Ncp;
int i, j;
for (i = 0; i < Ncorr; i++) {
complex float temp = 0.0f + 0.0f * I;
- for (j = 0; j < (OFDM_M + OFDM_NCP); j++) {
+ for (j = 0; j < (M + Ncp); j++) {
csam = conjf(ofdm->pilot_samples[j]);
temp = temp + (rx[i + j] * csam);
temp = temp + (rx[i + j + SFrame] * csam);
kiss_fft_cfg fftcfg = kiss_fft_alloc(Fs,0,NULL,NULL);
complex float fft_in[Fs];
complex float fft_out[Fs];
-
-
+ float C[Fs];
+ /* Zero FFT input array */
+ for(i = 0; i < Fs; i++){
+ fft_in[i] = 0;
+ }
+ /* shift and copy in NPsam samples to front of buffer for FFT'ing */
+ for(i = 0; i < NPSamp; i++){
+ fft_in[i] = rx[i + t_est] * conjf(ofdm->pilot_samples[i]);
+ }
+ kiss_fft(fftcfg,(kiss_fft_cpx*)fft_in,(kiss_fft_cpx*)fft_out);
+
+ /* Copy into output corr array, taking magnitude */
+ /* TODO: May be able to skip sqrt() in abs, since we're just looking for a maximum point down the line */
+ for(i = 0; i < Fs; i++){
+ C[i] = cabsf(fft_out[i]);
+ }
+
+ /* shift and copy in NPsam samples to front of buffer for FFT'ing */
+ for(i = 0; i < NPSamp; i++){
+ fft_in[i] = rx[i + t_est + SFrame] * conjf(ofdm->pilot_samples[i]);
+ }
+ kiss_fft(fftcfg,(kiss_fft_cpx*)fft_in,(kiss_fft_cpx*)fft_out);
+
+ /* Add into output corr array */
+ for(i = 0; i < Fs; i++){
+ C[i] += cabsf(fft_out[i]);
+ }
+
+ int fmax = 30;
+ int pmax_i,nmax_i;
+ float pmax,nmax;
+ float foff_est;
+ pmax_i = nmax_i = 0;
+ pmax = nmax = 0;
+ /* Search the positive and negative sides of the FFT to +/-fmax for peak */
+ for(i = 0; i < fmax; i++){
+ if(C[i] > pmax){
+ pmax = C[i];
+ pmax_i = i;
+ }
+ if(C[Fs-i-1] > nmax){
+ nmax = C[i];
+ nmax_i = i;
+ }
+ }
+ foff_est = (pmax > nmax) ? pmax_i : (nmax_i - fmax);
+ fprintf(stderr,"foff_est is %f\n",foff_est);
return t_est;
}
static void ofdm_txframe(struct OFDM *ofdm, complex float tx[OFDM_SAMPLESPERFRAME],
complex float *tx_sym_lin) {
- complex float aframe[OFDM_NS][OFDM_NC + 2];
- complex float asymbol[OFDM_M];
- complex float asymbol_cp[OFDM_M + OFDM_NCP];
+
+ int Fs = ofdm->config.Fs;
+ int Rs = ofdm->config.Rs;
+ int Bps = ofdm->config.bps;
+ int Nc = ofdm->config.Nc;
+ int M = ofdm->config.M;
+ int Ncp = ofdm->config.Ncp;
+ int Ns = ofdm->config.Ns;
+ int RowsPerFrame = ofdm->config.RowsPerFrame;
+ int SampsPerFrame = ofdm->config.SampsPerFrame;
+ int Fcenter = ofdm->config.Fcenter;
+
+ complex float aframe[Ns][Nc + 2];
+ complex float asymbol[M];
+ complex float asymbol_cp[M + Ncp];
int i, j, k, m;
/* initialize aframe to complex zero */
- for (i = 0; i < OFDM_NS; i++) {
- for (j = 0; j < (OFDM_NC + 2); j++) {
+ for (i = 0; i < Ns; i++) {
+ for (j = 0; j < (Nc + 2); j++) {
aframe[i][j] = 0.0f + 0.0f * I;
}
}
/* copy in a row of complex pilots to first row */
- for (i = 0; i < (OFDM_NC + 2); i++) {
+ for (i = 0; i < (Nc + 2); i++) {
aframe[0][i] = ofdm->pilots[i];
}
/* Place symbols in multi-carrier frame with pilots */
/* This will place boundary values of complex zero around data */
- for (i = 1; i <= OFDM_ROWSPERFRAME; i++) {
+ for (i = 1; i <= RowsPerFrame; i++) {
/* copy in the Nc complex values with [0 Nc 0] or (Nc + 2) total */
- for (j = 1; j < (OFDM_NC + 1); j++) {
- aframe[i][j] = tx_sym_lin[((i - 1) * OFDM_NC) + (j - 1)];
+ for (j = 1; j < (Nc + 1); j++) {
+ aframe[i][j] = tx_sym_lin[((i - 1) * Nc) + (j - 1)];
}
}
/* OFDM up-convert symbol by symbol so we can add CP */
- for (i = 0, m = 0; i < OFDM_NS; i++, m += (OFDM_M + OFDM_NCP)) {
+ for (i = 0, m = 0; i < Ns; i++, m += (M + Ncp)) {
idft(ofdm, asymbol, aframe[i]);
/* Copy the last Ncp columns to the front */
- for (j = (OFDM_M - OFDM_NCP), k = 0; j < OFDM_M; j++, k++) {
+ for (j = (M - Ncp), k = 0; j < M; j++, k++) {
asymbol_cp[k] = asymbol[j];
}
/* Now copy the whole row after it */
- for (j = OFDM_NCP, k = 0; k < OFDM_M; j++, k++) {
+ for (j = Ncp, k = 0; k < M; j++, k++) {
asymbol_cp[j] = asymbol[k];
}
/* Now move row to the tx reference */
- for (j = 0; j < (OFDM_M + OFDM_NCP); j++) {
+ for (j = 0; j < (M + Ncp); j++) {
tx[m + j] = asymbol_cp[j];
}
}
}
+/*
+ * Utility function to allocate a 2d array of dimension
+ * [sx][sy] with elements of elem size
+ */
+void **alloc_doubleary(size_t sx,size_t sy,size_t elem){
+ size_t i;
+ char ** ary = malloc(sizeof(void*) * sx);
+ if(ary == NULL){
+ return NULL;
+ }
+ *ary = malloc(elem * sx * sy);
+ if(*ary == NULL){
+ free(ary);
+ return NULL;
+ }
+ for(i=0; i<sx; i++){
+ ary[i] = ((*ary) + (sy*i*elem));
+ }
+ return (void**) ary;
+}
+
+void free_doubleary(void ** ary){
+ if(ary == NULL){
+ return;
+ }
+ if(*ary == NULL){
+ free(ary);
+ return;
+ }
+
+ free(*ary);
+
+ free(ary);
+}
+
/*
* ------------
* ofdm_create
struct OFDM *ofdm_create(const struct OFDM_CONFIG * config) {
struct OFDM *ofdm;
int i, j;
-
if ((ofdm = (struct OFDM *) malloc(sizeof (struct OFDM))) == NULL) {
return NULL;
}
/* Copy config structure */
+ /* TODO: validate config structure */
memcpy((void*)&ofdm->config,(void*)config,sizeof(struct OFDM_CONFIG));
+ int Fs = ofdm->config.Fs;
+ int Rs = ofdm->config.Rs;
+ int Bps = ofdm->config.bps;
+ int Nc = ofdm->config.Nc;
+ int M = ofdm->config.M;
+ int Ncp = ofdm->config.Ncp;
+ int Ns = ofdm->config.Ns;
+ int RowsPerFrame = ofdm->config.RowsPerFrame;
+ int SampsPerFrame = ofdm->config.SampsPerFrame;
+ int Fcenter = ofdm->config.Fcenter;
+
+ /* Allocate various buffers */
+ /* TODO: cleanup after failed malloc */
+ ofdm->pilot_samples = malloc(sizeof(complex float) * (M + Ncp));
+ ofdm->pilots = malloc(sizeof(complex float) * (Nc+2));
+ ofdm->rxbuf = malloc(sizeof(complex float) * ofdm->config.RxBufSize);
+ ofdm->w = malloc(sizeof(float) * (Nc+2));
+ ofdm->rx_amp = malloc(sizeof(float) * RowsPerFrame * Nc);
+ ofdm->aphase_est_pilot_log = malloc(sizeof(float) * RowsPerFrame * Nc);
/* store complex BPSK pilot symbols */
- for (i = 0; i < (OFDM_NC + 2); i++) {
+ for (i = 0; i < (Nc + 2); i++) {
ofdm->pilots[i] = ((float) pilotvalues[i]) + 0.0f * I;
}
/* carrier tables for up and down conversion */
- int Nlower = floorf((OFDM_CENTRE - OFDM_RS * (OFDM_NC / 2)) / OFDM_RS);
+ int Nlower = floorf((OFDM_CENTRE - OFDM_RS * (Nc / 2)) / OFDM_RS);
- for (i = 0, j = Nlower; i < (OFDM_NC + 2); i++, j++) {
+ for (i = 0, j = Nlower; i < (Nc + 2); i++, j++) {
/*
* 2 * pi * j/144 j=19..36
* j = 1 kHz to 2 kHz (1.5 kHz center)
ofdm->w[i] = TAU * (float) j / (OFDM_FS / OFDM_RS);
}
- for (i = 0; i < (OFDM_NC + 2); i++) {
- for (j = 0; j < OFDM_M; j++) {
+ ofdm->W = (complex float **) alloc_doubleary(Nc+2,M,sizeof(complex float));
+ ofdm->rx_sym = (complex float **) alloc_doubleary(Ns+3,Nc+2,sizeof(complex float));
+
+ for (i = 0; i < (Nc + 2); i++) {
+
+ for (j = 0; j < M; j++) {
ofdm->W[i][j] = cexpf(I * ofdm->w[i] * j);
}
}
- for (i = 0; i < (OFDM_NS + 3); i++) {
- for (j = 0; j < (OFDM_NC + 2); j++) {
+ for (i = 0; i < (Ns + 3); i++) {
+ for (j = 0; j < (Nc + 2); j++) {
ofdm->rx_sym[i][j] = 0.0f + 0.0f * I;
}
}
ofdm->foff_est_hz = 0.0f;
ofdm->sample_point = 0;
ofdm->timing_est = 0;
- ofdm->nin = OFDM_SAMPLESPERFRAME;
+ ofdm->nin = SampsPerFrame;
/* create the OFDM waveform */
- complex float temp[OFDM_M];
+ complex float temp[M];
idft(ofdm, temp, ofdm->pilots);
/* first copy the last Cyclic Prefix (CP) values */
- for (i = 0, j = (OFDM_M - OFDM_NCP); i < OFDM_NCP; i++, j++) {
+ for (i = 0, j = (M - Ncp); i < Ncp; i++, j++) {
ofdm->pilot_samples[i] = temp[j];
}
/* Now copy the whole thing after the above */
- for (i = OFDM_NCP, j = 0; j < OFDM_M; i++, j++) {
+ for (i = Ncp, j = 0; j < M; i++, j++) {
ofdm->pilot_samples[i] = temp[j];
}
return ofdm->nin;
}
-int ofdm_get_samples_per_frame() {
- return OFDM_SAMPLESPERFRAME;
+int ofdm_get_samples_per_frame(struct OFDM *ofdm) {
+ return ofdm->config.SampsPerFrame;
}
-int ofdm_get_max_samples_per_frame() {
- return OFDM_MAX_SAMPLESPERFRAME;
+int ofdm_get_max_samples_per_frame(struct OFDM *ofdm) {
+ return ofdm->config.SampsPerFrameMax;
}
void ofdm_set_verbose(struct OFDM *ofdm, int level) {
if (ofdm->timing_en == false) {
/* manually set ideal timing instant */
- ofdm->sample_point = (OFDM_NCP - 1);
+ ofdm->sample_point = (ofdm->config.Ncp - 1);
}
}
*/
void ofdm_mod(struct OFDM *ofdm, COMP result[OFDM_SAMPLESPERFRAME], const int *tx_bits) {
- int length = OFDM_BITSPERFRAME / OFDM_BPS;
- complex float tx[OFDM_SAMPLESPERFRAME];
+
+ int Fs = ofdm->config.Fs;
+ int Rs = ofdm->config.Rs;
+ int Bps = ofdm->config.bps;
+ int Nc = ofdm->config.Nc;
+ int M = ofdm->config.M;
+ int Ncp = ofdm->config.Ncp;
+ int Ns = ofdm->config.Ns;
+ int RowsPerFrame = ofdm->config.RowsPerFrame;
+ int SampsPerFrame = ofdm->config.SampsPerFrame;
+ int BitsPerFrame = ofdm->config.BitsPerFrame;
+ int Fcenter = ofdm->config.Fcenter;
+
+ int length = BitsPerFrame / Bps;
+ complex float tx[SampsPerFrame];
complex float tx_sym_lin[length];
int dibit[2];
int s, i;
- if (OFDM_BPS == 1) {
+ if (Bps == 1) {
/* Here we will have Nbitsperframe / 1 */
for (s = 0; s < length; s++) {
tx_sym_lin[s] = (float) (2 * tx_bits[s] - 1) + 0.0f * I;
}
- } else if (OFDM_BPS == 2) {
+ } else if (Bps == 2) {
/* Here we will have Nbitsperframe / 2 */
for (s = 0, i = 0; i < length; s += 2, i++) {
/* convert to comp */
- for (i = 0; i < OFDM_SAMPLESPERFRAME; i++) {
+ for (i = 0; i < SampsPerFrame; i++) {
result[i].real = crealf(tx[i]);
result[i].imag = cimagf(tx[i]);
}
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];
+
+ int Fs = ofdm->config.Fs;
+ int Rs = ofdm->config.Rs;
+ int Bps = ofdm->config.bps;
+ int Nc = ofdm->config.Nc;
+ int M = ofdm->config.M;
+ int Ncp = ofdm->config.Ncp;
+ int Ns = ofdm->config.Ns;
+ int RowsPerFrame = ofdm->config.RowsPerFrame;
+ int SampsPerFrame = ofdm->config.SampsPerFrame;
+ int FtWindowWidth = ofdm->config.FtWindowWidth;
+ int BitsPerFrame = ofdm->config.BitsPerFrame;
+ int Fcenter = ofdm->config.Fcenter;
+ int RxBufSize = ofdm->config.RxBufSize;
+
+ float aphase_est_pilot[Nc + 2];
+ float aamp_est_pilot[Nc + 2];
float freq_err_hz;
int i, j, k, rr, st, en, ft_est;
/* shift the buffer left based on nin */
- for (i = 0, j = ofdm->nin; i < (OFDM_RXBUF - ofdm->nin); i++, j++) {
+ for (i = 0, j = ofdm->nin; i < (RxBufSize - ofdm->nin); i++, j++) {
ofdm->rxbuf[i] = ofdm->rxbuf[j];
}
/* insert latest input samples onto tail of rxbuf */
- for (i = (OFDM_RXBUF - ofdm->nin), j = 0; i < OFDM_RXBUF; i++, j++) {
+ for (i = (RxBufSize - ofdm->nin), j = 0; i < RxBufSize; i++, j++) {
ofdm->rxbuf[i] = rxbuf_in[j].real + rxbuf_in[j].imag * I;
}
* get user and calculated freq offset
*/
- float woff_est = TAU * ofdm->foff_est_hz / OFDM_FS;
+ float woff_est = TAU * ofdm->foff_est_hz / (float)(Fs);
/* update timing estimate -------------------------------------------------- */
if (ofdm->timing_en == true) {
/* update timing at start of every frame */
- st = ((OFDM_M + OFDM_NCP) + OFDM_SAMPLESPERFRAME) - floorf(OFDM_FTWINDOWWIDTH / 2) + ofdm->timing_est;
- en = st + OFDM_SAMPLESPERFRAME - 1 + (OFDM_M + OFDM_NCP) + OFDM_FTWINDOWWIDTH;
+ st = ((M + Ncp) + SampsPerFrame) - floorf(FtWindowWidth / 2) + ofdm->timing_est;
+ en = st + SampsPerFrame - 1 + (M + Nc) + FtWindowWidth;
complex float work[(en - st)];
*/
for (i = st, j = 0; i < en; i++, j++) {
+ /* TODO: Look into reducing cexpf usage */
work[j] = ofdm->rxbuf[i] * cexpf(-I * woff_est * i);
}
ft_est = coarse_sync(ofdm, work, (en - st));
- ofdm->timing_est += (ft_est - ceilf(OFDM_FTWINDOWWIDTH / 2));
+ ofdm->timing_est += (ft_est - ceilf(FtWindowWidth / 2));
if (ofdm->verbose > 1) {
fprintf(stdout, " ft_est: %2d timing_est: %2d sample_point: %2d\n", ft_est, ofdm->timing_est, ofdm->sample_point);
/* Black magic to keep sample_point inside cyclic prefix. Or something like that. */
- ofdm->sample_point = max(ofdm->timing_est + (OFDM_NCP / 4), ofdm->sample_point);
- ofdm->sample_point = min(ofdm->timing_est + OFDM_NCP, ofdm->sample_point);
+ ofdm->sample_point = max(ofdm->timing_est + (Ncp / 4), ofdm->sample_point);
+ ofdm->sample_point = min(ofdm->timing_est + Ncp, ofdm->sample_point);
}
/*
* The average of the four pilot symbols is our phase estimation.
*/
- for (i = 0; i < (OFDM_NS + 3); i++) {
- for (j = 0; j < (OFDM_NC + 2); j++) {
+ for (i = 0; i < (Ns + 3); i++) {
+ for (j = 0; j < (Nc + 2); j++) {
ofdm->rx_sym[i][j] = 0.0f + 0.0f * I;
}
}
* "Previous" pilot symbol is one modem frame above.
*/
- st = (OFDM_M + OFDM_NCP) + 1 + ofdm->sample_point;
- en = st + OFDM_M;
+ st = (M + Ncp) + 1 + ofdm->sample_point;
+ en = st + M;
- complex float work[OFDM_M];
+ complex float work[M];
/* down-convert at current timing instant---------------------------------- */
* In this routine we also process the current data symbols.
*/
- for (rr = 0; rr < (OFDM_NS + 1); rr++) {
- st = (OFDM_M + OFDM_NCP) + OFDM_SAMPLESPERFRAME + (rr * (OFDM_M + OFDM_NCP)) + 1 + ofdm->sample_point;
- en = st + OFDM_M;
+ for (rr = 0; rr < (Ns + 1); rr++) {
+ st = (M + Ncp) + SampsPerFrame + (rr * (M + Ncp)) + 1 + ofdm->sample_point;
+ en = st + M;
/* down-convert at current timing instant---------------------------------- */
* We only want the "future" pilot symbol, to perform the averaging of all pilots.
*/
- st = (OFDM_M + OFDM_NCP) + (3 * OFDM_SAMPLESPERFRAME) + 1 + ofdm->sample_point;
- en = st + OFDM_M;
+ st = (M + Ncp) + (3 * SampsPerFrame) + 1 + ofdm->sample_point;
+ en = st + M;
/* down-convert at current timing instant---------------------------------- */
* +----------------------+
*/
- dft(ofdm, ofdm->rx_sym[OFDM_NS + 2], work);
+ dft(ofdm, ofdm->rx_sym[Ns + 2], work);
/*
* We are finished now with the DFT and down conversion
*/
complex float freq_err_rect = conjf(vector_sum(ofdm->rx_sym[1],
- OFDM_NC + 2)) * vector_sum(ofdm->rx_sym[OFDM_NS + 1], OFDM_NC + 2);
+ Nc + 2)) * vector_sum(ofdm->rx_sym[Ns + 1], Nc + 2);
/* prevent instability in atan(im/re) when real part near 0 */
freq_err_rect = freq_err_rect + 1E-6f;
- freq_err_hz = cargf(freq_err_rect) * OFDM_RS / (TAU * OFDM_NS);
+ freq_err_hz = cargf(freq_err_rect) * OFDM_RS / (TAU * Ns);
ofdm->foff_est_hz += (ofdm->foff_est_gain * freq_err_hz);
}
/* OK - now estimate and correct pilot phase ---------------------------------- */
- for (i = 0; i < (OFDM_NC + 2); i++) {
+ for (i = 0; i < (Nc + 2); i++) {
aphase_est_pilot[i] = 10.0f;
aamp_est_pilot[i] = 0.0f;
}
* Then average the phase surrounding each of the data symbols.
*/
- for (i = 1; i < (OFDM_NC + 1); i++) {
+ for (i = 1; i < (Nc + 1); i++) {
complex float symbol[3];
for (j = (i - 1), k = 0; j < (i + 2); j++, k++) {
aphase_est_pilot_rect = vector_sum(symbol, 3);
for (j = (i - 1), k = 0; j < (i + 2); j++, k++) {
- symbol[k] = ofdm->rx_sym[OFDM_NS + 1][j] * conjf(ofdm->pilots[j]); /* next pilot conjugate */
+ symbol[k] = ofdm->rx_sym[Ns + 1][j] * conjf(ofdm->pilots[j]); /* next pilot conjugate */
}
aphase_est_pilot_rect = aphase_est_pilot_rect + vector_sum(symbol, 3);
aphase_est_pilot_rect = aphase_est_pilot_rect + vector_sum(symbol, 3);
for (j = (i - 1), k = 0; j < (i + 2); j++, k++) {
- symbol[k] = ofdm->rx_sym[OFDM_NS + 2][j] * ofdm->pilots[j]; /* last pilot */
+ symbol[k] = ofdm->rx_sym[Ns + 2][j] * ofdm->pilots[j]; /* last pilot */
}
aphase_est_pilot_rect = aphase_est_pilot_rect + vector_sum(symbol, 3);
*/
complex float rx_corr;
+ complex float rx_np[RowsPerFrame * Nc];
int abit[2];
int bit_index = 0;
- for (rr = 0; rr < OFDM_ROWSPERFRAME; rr++) {
+ for (rr = 0; rr < RowsPerFrame; rr++) {
/*
* Note the i has an index of 1 to 16, so we ignore carriers 0 and 17.
*
* Also note we are using sym[2..8] or the seven data symbols.
*/
- for (i = 1; i < (OFDM_NC + 1); i++) {
+ for (i = 1; i < (Nc + 1); i++) {
if (ofdm->phase_est_en == true) {
rx_corr = ofdm->rx_sym[rr + 2][i] * cexpf(-I * aphase_est_pilot[i]);
} else {
* without the pilots. Thus, the name rx (no pilot) np
*/
- ofdm->rx_np[(rr * OFDM_NC) + (i - 1)] = rx_corr;
+ rx_np[(rr * Nc) + (i - 1)] = rx_corr;
/*
* Note even though amp ests are the same for each col,
* so convenient to log them all
*/
- ofdm->rx_amp[(rr * OFDM_NC) + (i - 1)] = aamp_est_pilot[i];
+ ofdm->rx_amp[(rr * Nc) + (i - 1)] = aamp_est_pilot[i];
/*
* Note like amps in this implementation phase ests are the
* same for each col, but we log them for each symbol anyway
*/
- ofdm->aphase_est_pilot_log[(rr * OFDM_NC) + (i - 1)] = aphase_est_pilot[i];
+ ofdm->aphase_est_pilot_log[(rr * Nc) + (i - 1)] = aphase_est_pilot[i];
if (OFDM_BPS == 1) {
rx_bits[bit_index++] = crealf(rx_corr) > 0.0f;
/* Adjust nin to take care of sample clock offset */
- ofdm->nin = OFDM_SAMPLESPERFRAME;
+ ofdm->nin = SampsPerFrame;
if (ofdm->timing_en == true) {
- int thresh = (OFDM_M + OFDM_NCP) / 8;
- int tshift = (OFDM_M + OFDM_NCP) / 4;
+ int thresh = (M + Ncp) / 8;
+ int tshift = (M + Ncp) / 4;
if (ofdm->timing_est > thresh) {
- ofdm->nin = OFDM_SAMPLESPERFRAME + tshift;
+ ofdm->nin = SampsPerFrame + tshift;
ofdm->timing_est -= tshift;
ofdm->sample_point -= tshift;
} else if (ofdm->timing_est < -thresh) {
- ofdm->nin = OFDM_SAMPLESPERFRAME - tshift;
+ ofdm->nin = SampsPerFrame - tshift;
ofdm->timing_est += tshift;
ofdm->sample_point += tshift;
}
}
+
+ int timing_est_log = ofdm->timing_est + 1;
+ int sample_point_log = ofdm->sample_point + 1;
+
+ modem_probe_samp_f("foff_hz_log_c",&(ofdm->foff_est_hz),1);
+ modem_probe_samp_i("timing_est_log_c",&timing_est_log,1);
+ modem_probe_samp_i("sample_point_log_c",&sample_point_log,1);
+ modem_probe_samp_cft("rxbuf_log_c",ofdm->rxbuf,ofdm->config.RxBufSize);
+ modem_probe_samp_cft("rx_np_log_c",&rx_np[0],RowsPerFrame * Nc);
}
#include <complex.h>
#include <stdbool.h>
+#include <stdint.h>
#include "codec2_ofdm.h"
#define TAU (2.0f * M_PI) /* mathematical constant */
-#define OFDM_NC 16 /* N Carriers */
+#define OFDM_NCX 16 /* N Carriers */
#define OFDM_TS 0.018f /* Symbol time */
#define OFDM_RS (1.0f / OFDM_TS) /* Symbol rate */
#define OFDM_FS 8000.0f /* Sample rate */
#define OFDM_BPS 2 /* Bits per symbol */
#define OFDM_TCP 0.002f /* ? */
-#define OFDM_NS 8 /* */
+#define OFDM_NS 8 /* Symbols per frame (number of rows incl pilot) */
#define OFDM_CENTRE 1500.0f /* Center frequency */
/* To prevent C99 warning */
/* ? */
#define OFDM_FTWINDOWWIDTH 11
/* Bits per frame (duh) */
-#define OFDM_BITSPERFRAME ((OFDM_NS - 1) * (OFDM_NC * OFDM_BPS))
+#define OFDM_BITSPERFRAME ((OFDM_NS - 1) * (OFDM_NCX * OFDM_BPS))
/* Rows per frame */
-#define OFDM_ROWSPERFRAME (OFDM_BITSPERFRAME / (OFDM_NC * OFDM_BPS))
+#define OFDM_ROWSPERFRAME (OFDM_BITSPERFRAME / (OFDM_NCX * OFDM_BPS))
/* Samps per frame */
#define OFDM_SAMPLESPERFRAME (OFDM_NS * (OFDM_M + OFDM_NCP))
/* Dummy struct for now, will contain constant configuration for OFDM modem */
struct OFDM_CONFIG{
- int a;
+ int32_t Nc;
+ int32_t Ts;
+ int32_t Rs;
+ int32_t Fs;
+ int32_t bps;
+ int32_t Tcp;
+ int32_t Ns;
+ int32_t Fcenter;
+ int32_t M;
+ int32_t Ncp;
+ int32_t FtWindowWidth;
+ int32_t BitsPerFrame;
+ int32_t SampsPerFrame;
+ int32_t SampsPerFrameMax;
+ int32_t RxBufSize;
+ int32_t RowsPerFrame;
};
-
struct OFDM {
struct OFDM_CONFIG config;
float foff_est_gain;
bool foff_est_en;
bool phase_est_en;
- complex float pilot_samples[OFDM_M + OFDM_NCP];
- complex float W[OFDM_NC + 2][OFDM_M];
- complex float rxbuf[OFDM_RXBUF];
- complex float pilots[OFDM_NC + 2];
- float w[OFDM_NC + 2];
+ //complex float pilot_samples[OFDM_M + OFDM_NCP];
+ //complex float W[OFDM_NCX + 2][OFDM_M];
+ //complex float rxbuf[OFDM_RXBUF];
+ //complex float pilots[OFDM_NC + 2];
+ //float w[OFDM_NC + 2];
+
+ complex float ** W;
+ complex float * pilots;
+ complex float * pilot_samples;
+ complex float * rxbuf;
+ float * w;
+
/* Demodulator data */
- complex float rx_sym[OFDM_NS + 3][OFDM_NC + 2];
- complex float rx_np[OFDM_ROWSPERFRAME * OFDM_NC];
- float rx_amp[OFDM_ROWSPERFRAME * OFDM_NC];
- float aphase_est_pilot_log[OFDM_ROWSPERFRAME * OFDM_NC];
+ //complex float rx_sym[OFDM_NS + 3][OFDM_NCX + 2];
+ //complex float rx_np[OFDM_ROWSPERFRAME * OFDM_NCX];
+ //float rx_amp[OFDM_ROWSPERFRAME * OFDM_NCX];
+ //float aphase_est_pilot_log[OFDM_ROWSPERFRAME * OFDM_NCX];
+
+ complex float ** rx_sym;
+ float * rx_amp;
+ float * aphase_est_pilot_log;
};
#ifdef __cplusplus
add_executable(tdeframer tdeframer.c)
target_link_libraries(tdeframer m codec2)
-add_executable(tofdm tofdm.c ../src/ofdm.c ../src/octave.c ../src/kiss_fft.c)
+add_definitions(-DMODEMPROBE_ENABLE -DXXXXX)
+add_executable(tofdm tofdm.c ../src/ofdm.c ../src/octave.c ../src/kiss_fft.c ../src/modem_probe.c)
target_link_libraries(tofdm m)
add_executable(tfreedv_data_channel tfreedv_data_channel.c)
#include <math.h>
#include <complex.h>
+#define MODEMPROBE_ENABLE
+
#include "ofdm_internal.h"
#include "codec2_ofdm.h"
#include "octave.h"
#include "test_bits_ofdm.h"
#include "comp_prim.h"
+#include "modem_probe.h"
+
+#define OFDM_NC 16
#define NFRAMES 30
-#define SAMPLE_CLOCK_OFFSET_PPM 100
-#define FOFF_HZ 0.5f
+//#define SAMPLE_CLOCK_OFFSET_PPM 100
+//#define FOFF_HZ 5.0f
/*---------------------------------------------------------------------------*\
FILE *fout;
int f,i,j;
+ int sample_clock_offset_ppm = 100;
+ float foff_hz = 0.1;
+ int nframes = 30;
+
ofdm = ofdm_create(OFDM_CONFIG_700D);
assert(ofdm != NULL);
Channel
\*---------------------------------------------------------*/
- fs_offset(rx_log, tx_log, samples_per_frame*NFRAMES, SAMPLE_CLOCK_OFFSET_PPM);
+ fs_offset(rx_log, tx_log, samples_per_frame*NFRAMES, sample_clock_offset_ppm);
COMP foff_phase_rect = {1.0f, 0.0f};
- freq_shift(rx_log, rx_log, FOFF_HZ, &foff_phase_rect, samples_per_frame * NFRAMES);
+ freq_shift(rx_log, rx_log, foff_hz, &foff_phase_rect, samples_per_frame * NFRAMES);
/* --------------------------------------------------------*\
Demod
int nin_tot = 0;
+ modem_probe_init("ofdm","ofdm_test.txt");
+
/* disable estimators for initial testing */
ofdm_set_verbose(ofdm, true);
/* rx vector logging -----------------------------------*/
assert(nin_tot < samples_per_frame*NFRAMES);
- memcpy(&rxbuf_in_log[nin_tot], rxbuf_in, sizeof(COMP)*nin);
+ //memcpy(&rxbuf_in_log[nin_tot], rxbuf_in, sizeof(COMP)*nin);
+ modem_probe_samp_cft("rxbuf_in_log_c",rxbuf_in,nin);
+
nin_tot += nin;
- for(i=0; i<OFDM_RXBUF; i++) {
+ /*for(i=0; i<OFDM_RXBUF; i++) {
rxbuf_log[OFDM_RXBUF*f+i].real = crealf(ofdm->rxbuf[i]);
rxbuf_log[OFDM_RXBUF*f+i].imag = cimagf(ofdm->rxbuf[i]);
- }
+ }*/
for (i = 0; i < (OFDM_NS + 3); i++) {
for (j = 0; j < (OFDM_NC + 2); j++) {
/* note corrected phase (rx no phase) is one big linear array for frame */
- for (i = 0; i < OFDM_ROWSPERFRAME*OFDM_NC; i++) {
+ /*for (i = 0; i < OFDM_ROWSPERFRAME*OFDM_NC; i++) {
rx_np_log[OFDM_ROWSPERFRAME*OFDM_NC*f + i].real = crealf(ofdm->rx_np[i]);
rx_np_log[OFDM_ROWSPERFRAME*OFDM_NC*f + i].imag = cimagf(ofdm->rx_np[i]);
- }
+ }*/
/* note phase/amp ests the same for each col, but check them all anyway */
}
}
- foff_hz_log[f] = ofdm->foff_est_hz;
- 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));
+ //foff_hz_log[f] = ofdm->foff_est_hz;
+ //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 */
+
+ modem_probe_samp_i("rx_bits_log_c",rx_bits,OFDM_BITSPERFRAME);
+ //memcpy(&rx_bits_log[OFDM_BITSPERFRAME*f], rx_bits, sizeof(rx_bits));
}
/*---------------------------------------------------------*\
by tofdm.m Octave script
\*---------------------------------------------------------*/
+ modem_probe_close();
+
+
fout = fopen("tofdm_out.txt","wt");
assert(fout != NULL);
fprintf(fout, "# Created by tofdm.c\n");
octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, OFDM_BITSPERFRAME*NFRAMES);
octave_save_complex(fout, "tx_log_c", (COMP*)tx_log, 1, samples_per_frame*NFRAMES, samples_per_frame*NFRAMES);
octave_save_complex(fout, "rx_log_c", (COMP*)rx_log, 1, samples_per_frame*NFRAMES, samples_per_frame*NFRAMES);
- octave_save_complex(fout, "rxbuf_in_log_c", (COMP*)rxbuf_in_log, 1, nin_tot, nin_tot);
- octave_save_complex(fout, "rxbuf_log_c", (COMP*)rxbuf_log, 1, OFDM_RXBUF*NFRAMES, OFDM_RXBUF*NFRAMES);
+ //octave_save_complex(fout, "rxbuf_in_log_c", (COMP*)rxbuf_in_log, 1, nin_tot, nin_tot);
+ //octave_save_complex(fout, "rxbuf_log_c_x", (COMP*)rxbuf_log, 1, OFDM_RXBUF*NFRAMES, OFDM_RXBUF*NFRAMES);
octave_save_complex(fout, "rx_sym_log_c", (COMP*)rx_sym_log, (OFDM_NS + 3)*NFRAMES, OFDM_NC + 2, OFDM_NC + 2);
octave_save_float(fout, "phase_est_pilot_log_c", (float*)phase_est_pilot_log, OFDM_ROWSPERFRAME*NFRAMES, OFDM_NC, OFDM_NC);
octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, 1, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES);
- octave_save_float(fout, "foff_hz_log_c", foff_hz_log, NFRAMES, 1, 1);
- octave_save_int(fout, "timing_est_log_c", timing_est_log, NFRAMES, 1);
- octave_save_int(fout, "sample_point_log_c", sample_point_log, NFRAMES, 1);
- octave_save_complex(fout, "rx_np_log_c", (COMP*)rx_np_log, 1, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES);
- octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, OFDM_BITSPERFRAME*NFRAMES);
+ //octave_save_float(fout, "foff_hz_log_c", foff_hz_log, NFRAMES, 1, 1);
+ //octave_save_int(fout, "timing_est_log_c", timing_est_log, NFRAMES, 1);
+ //ctave_save_int(fout, "sample_point_log_c", sample_point_log, NFRAMES, 1);
+ //octave_save_complex(fout, "rx_np_log_c", (COMP*)rx_np_log, 1, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES);
+ //octave_save_int(fout, "rx_bits_log_cx", rx_bits_log, 1, OFDM_BITSPERFRAME*NFRAMES);
fclose(fout);
ofdm_destroy(ofdm);