%
% Octave script for comparing Octave and C versions of OFDZM modem
+% ------------------------------------------------------------------
-Nframes = 3;
+Nframes = 30;
+sample_clock_offset_ppm = 100;
more off; format;
ofdm_lib;
tx_log = [tx_log ofdm_mod(states, tx_bits)];
end
-% Channel simulation
+% Channel simulation ----------------------------------------------
-rx = tx_log;
+rx_log = sample_clock_offset(tx_log, sample_clock_offset_ppm);
+
+% Rx ---------------------------------------------------------------
% Init rx with ideal timing so we can test with timing estimation disabled
-Nsam = length(rx);
+Nsam = length(rx_log);
prx = 1;
nin = Nsamperframe+2*(M+Ncp);
-states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx(prx:nin);
+states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx_log(prx:nin);
prx += nin;
rxbuf_log = []; rxbuf_in_log = []; rx_sym_log = []; foff_hz_log = [];
rxbuf_in = zeros(1,nin);
%printf("nin: %d prx: %d lnew: %d\n", nin, prx, lnew);
if lnew
- rxbuf_in(1:lnew) = rx(prx:prx+lnew-1);
+ rxbuf_in(1:lnew) = rx_log(prx:prx+lnew-1);
end
prx += lnew;
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(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])
check(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(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');
+
#include "octave.h"
#include "test_bits_ofdm.h"
-#define NFRAMES 3
+#define NFRAMES 30
+#define SAMPLE_CLOCK_OFFSET_PPM 100
+
+int cohpsk_fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm);
int main(int argc, char *argv[])
{
int tx_bits_log[OFDM_BITSPERFRAME*NFRAMES];
COMP tx_log[samples_per_frame*NFRAMES];
+ COMP rx_log[samples_per_frame*NFRAMES];
COMP rxbuf_in_log[max_samples_per_frame*NFRAMES];
COMP rxbuf_log[OFDM_RXBUF*NFRAMES];
COMP rx_sym_log[(OFDM_NS + 3)*NFRAMES][OFDM_NC + 2];
}
/* --------------------------------------------------------*\
- Demod
+ Channel
\*---------------------------------------------------------*/
- COMP *rx = tx_log;
+ cohpsk_fs_offset(rx_log, tx_log, samples_per_frame*NFRAMES, SAMPLE_CLOCK_OFFSET_PPM);
+
+ /* --------------------------------------------------------*\
+ Demod
+ \*---------------------------------------------------------*/
/* Init rx with ideal timing so we can test with timing estimation disabled */
COMP rxbuf_in[max_samples_per_frame];
for (i=0; i<nin; i++,prx++) {
- ofdm->rxbuf[OFDM_RXBUF-nin+i] = rx[prx].real + I*rx[prx].imag;
+ ofdm->rxbuf[OFDM_RXBUF-nin+i] = rx_log[prx].real + I*rx_log[prx].imag;
}
int nin_tot = 0;
if (lnew) {
for(i=0; i<lnew; i++, prx++) {
- rxbuf_in[i] = rx[prx];
+ rxbuf_in[i] = rx_log[prx];
}
}
assert(prx <= max_samples_per_frame*NFRAMES);
octave_save_complex(fout, "W_c", (COMP*)ofdm->W, OFDM_NC + 2, OFDM_M, OFDM_M);
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, "rx_sym_log_c", (COMP*)rx_sym_log, (OFDM_NS + 3)*NFRAMES, OFDM_NC + 2, OFDM_NC + 2);
return 0;
}
+/*---------------------------------------------------------------------------*\
+
+ FUNCTION....: cohpsk_fs_offset()
+ AUTHOR......: David Rowe
+ DATE CREATED: May 2015
+
+ Simulates small Fs offset between mod and demod.
+
+\*---------------------------------------------------------------------------*/
+
+int cohpsk_fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm)
+{
+ double tin, f;
+ int tout, t1, t2;
+
+ tin = 0.0; tout = 0;
+ while (tin < n) {
+ t1 = floor(tin);
+ t2 = ceil(tin);
+ f = tin - t1;
+ out[tout].real = (1.0-f)*in[t1].real + f*in[t2].real;
+ out[tout].imag = (1.0-f)*in[t1].imag + f*in[t2].imag;
+ tout += 1;
+ tin += 1.0 + sample_rate_ppm/1E6;
+ //printf("tin: %f tout: %d f: %f\n", tin, tout, f);
+ }
+
+ return tout;
+}
+