/* Concrete definition of 700D parameters */
const struct OFDM_CONFIG OFDM_CONFIG_700D_C = {
.Nc = 16,
- .Ts = -1,
- .Rs = -1,
+ .Ts = 0.018f,
+ .Rs = (1.0/0.018),
.Fs = 8000,
.bps = 2,
.Tcp = -1,
static complex float vector_sum(complex float *, int);
static complex float qpsk_mod(int *);
static void qpsk_demod(complex float, int *);
-static void ofdm_txframe(struct OFDM *, complex float [OFDM_SAMPLESPERFRAME], complex float *);
+static void ofdm_txframe(struct OFDM *, complex float [], complex float *);
static int coarse_sync(struct OFDM *, complex float *, int);
/* Defines */
static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length) {
complex float csam;
- 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;
+ const int Fs = ofdm->config.Fs;
+ const int M = ofdm->config.M;
+ const int Ncp = ofdm->config.Ncp;
+ const int SampsPerFrame = ofdm->config.SampsPerFrame;
+ const int Ncorr = length - (SampsPerFrame + (M + Ncp));
+
float corr[Ncorr];
int NPSamp = M + Ncp;
int i, 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);
+ temp = temp + (rx[i + j + SampsPerFrame] * csam);
}
corr[i] = cabsf(temp);
/* Coarse frequency estimation */
/* TODO: Move FFT config to ofdm init and ofdm struct */
- kiss_fft_cfg fftcfg = kiss_fft_alloc(Fs,0,NULL,NULL);
+ kiss_fft_cfg fftcfg = ofdm->sync_fft_cfg;
complex float fft_in[Fs];
complex float fft_out[Fs];
float C[Fs];
/* 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]);
+ fft_in[i] = rx[i + t_est + SampsPerFrame] * conjf(ofdm->pilot_samples[i]);
}
kiss_fft(fftcfg,(kiss_fft_cpx*)fft_in,(kiss_fft_cpx*)fft_out);
}
}
foff_est = (pmax > nmax) ? pmax_i : (nmax_i - fmax);
- fprintf(stderr,"foff_est is %f\n",foff_est);
+ //fprintf(stderr,"foff_est is %f\n",foff_est);
return t_est;
}
* ----------------------------------------------
*/
-static void ofdm_txframe(struct OFDM *ofdm, complex float tx[OFDM_SAMPLESPERFRAME],
+static void ofdm_txframe(struct OFDM *ofdm, complex float tx[],
complex float *tx_sym_lin) {
- 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;
+ const int Nc = ofdm->config.Nc;
+ const int M = ofdm->config.M;
+ const int Ncp = ofdm->config.Ncp;
+ const int Ns = ofdm->config.Ns;
+ const int RowsPerFrame = ofdm->config.RowsPerFrame;
complex float aframe[Ns][Nc + 2];
complex float asymbol[M];
return (void**) ary;
}
+/*
+ * Utility function to free array allocated with alloc_doubleary()
+ * Performs null check before freeing anything
+ */
void free_doubleary(void ** ary){
if(ary == NULL){
return;
}
free(*ary);
-
free(ary);
}
+/* Utility function to null-check before freeing */
+static void free_nc(void * ptr){
+ if(ptr != NULL){
+ free(ptr);
+ }
+}
+
/*
* ------------
* ofdm_create
/* 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;
+ const int Fs = ofdm->config.Fs;
+ const int Rs = ofdm->config.Rs;
+ const int Nc = ofdm->config.Nc;
+ const int M = ofdm->config.M;
+ const int Ncp = ofdm->config.Ncp;
+ const int Ns = ofdm->config.Ns;
+ const int RowsPerFrame = ofdm->config.RowsPerFrame;
+ const int SampsPerFrame = ofdm->config.SampsPerFrame;
+ const int Fcenter = ofdm->config.Fcenter;
+ complex float temp[M];
/* Allocate various buffers */
/* TODO: cleanup after failed malloc */
ofdm->pilot_samples = malloc(sizeof(complex float) * (M + Ncp));
+ if(ofdm->pilot_samples == NULL) goto ofdm_fail_cleanup;
+
ofdm->pilots = malloc(sizeof(complex float) * (Nc+2));
+ if(ofdm->pilots == NULL) goto ofdm_fail_cleanup;
+
ofdm->rxbuf = malloc(sizeof(complex float) * ofdm->config.RxBufSize);
+ if(ofdm->rxbuf == NULL) goto ofdm_fail_cleanup;
+
ofdm->w = malloc(sizeof(float) * (Nc+2));
+ if(ofdm->w == NULL) goto ofdm_fail_cleanup;
+
ofdm->rx_amp = malloc(sizeof(float) * RowsPerFrame * Nc);
+ if(ofdm->rx_amp == NULL) goto ofdm_fail_cleanup;
+
ofdm->aphase_est_pilot_log = malloc(sizeof(float) * RowsPerFrame * Nc);
+ if(ofdm->aphase_est_pilot_log == NULL) goto ofdm_fail_cleanup;
+
+ ofdm->sync_fft_cfg = kiss_fft_alloc(Fs,0,NULL,NULL);
+ if(ofdm->sync_fft_cfg == NULL) goto ofdm_fail_cleanup;
/* store complex BPSK pilot symbols */
/* carrier tables for up and down conversion */
- int Nlower = floorf((OFDM_CENTRE - OFDM_RS * (Nc / 2)) / OFDM_RS);
+ int Nlower = floorf(( (float)(Fcenter) - Rs * ((float)Nc / 2)) / Rs);
for (i = 0, j = Nlower; i < (Nc + 2); i++, j++) {
/*
* j = 1 kHz to 2 kHz (1.5 kHz center)
*/
- ofdm->w[i] = TAU * (float) j / (OFDM_FS / OFDM_RS);
+ ofdm->w[i] = TAU * (float) j / ((float)Fs / Rs);
}
ofdm->W = (complex float **) alloc_doubleary(Nc+2,M,sizeof(complex float));
+ if(ofdm->W == NULL) goto ofdm_fail_cleanup;
+
ofdm->rx_sym = (complex float **) alloc_doubleary(Ns+3,Nc+2,sizeof(complex float));
+ if(ofdm->rx_sym == NULL) goto ofdm_fail_cleanup;
for (i = 0; i < (Nc + 2); i++) {
/* create the OFDM waveform */
- complex float temp[M];
-
idft(ofdm, temp, ofdm->pilots);
/*
}
return ofdm; /* Success */
+
+ /* Deal with a failed malloc or something */
+ ofdm_fail_cleanup:
+ /* Make sure ofdm points to a vaild struct */
+ if(ofdm == NULL)
+ return NULL;
+
+ free_nc(ofdm->pilots);
+ free_nc(ofdm->pilot_samples);
+ free_nc(ofdm->rxbuf);
+ free_nc(ofdm->w);
+ free_nc(ofdm->rx_amp);
+ free_nc(ofdm->aphase_est_pilot_log);
+ free_doubleary((void**)ofdm->W);
+ free_doubleary((void**)ofdm->rx_sym);
+ if(ofdm->sync_fft_cfg!=NULL) kiss_fft_free(ofdm->sync_fft_cfg);
+ free_nc(ofdm);
+
+ return NULL;
}
void ofdm_destroy(struct OFDM *ofdm) {
- free(ofdm);
+ if(ofdm == NULL)
+ return;
+
+ free_nc(ofdm->pilots);
+ free_nc(ofdm->pilot_samples);
+ free_nc(ofdm->rxbuf);
+ free_nc(ofdm->w);
+ free_nc(ofdm->rx_amp);
+ free_nc(ofdm->aphase_est_pilot_log);
+ free_doubleary((void**)ofdm->W);
+ free_doubleary((void**)ofdm->rx_sym);
+ if(ofdm->sync_fft_cfg!=NULL) kiss_fft_free(ofdm->sync_fft_cfg);
+ free_nc(ofdm);
}
int ofdm_get_nin(struct OFDM *ofdm) {
* --------------------------------------
*/
-void ofdm_mod(struct OFDM *ofdm, COMP result[OFDM_SAMPLESPERFRAME], const int *tx_bits) {
+void ofdm_mod(struct OFDM *ofdm, COMP result[], const int *tx_bits) {
- 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;
+ const int Bps = ofdm->config.bps;
+ const int SampsPerFrame = ofdm->config.SampsPerFrame;
+ const int BitsPerFrame = ofdm->config.BitsPerFrame;
int length = BitsPerFrame / Bps;
complex float tx[SampsPerFrame];
void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) {
complex float aphase_est_pilot_rect;
- 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;
+ const int Fs = ofdm->config.Fs;
+ const float Rs = ofdm->config.Rs;
+ const int Bps = ofdm->config.bps;
+ const int Nc = ofdm->config.Nc;
+ const int M = ofdm->config.M;
+ const int Ncp = ofdm->config.Ncp;
+ const int Ns = ofdm->config.Ns;
+ const int RowsPerFrame = ofdm->config.RowsPerFrame;
+ const int SampsPerFrame = ofdm->config.SampsPerFrame;
+ const int FtWindowWidth = ofdm->config.FtWindowWidth;
+ const int RxBufSize = ofdm->config.RxBufSize;
float aphase_est_pilot[Nc + 2];
float aamp_est_pilot[Nc + 2];
freq_err_rect = freq_err_rect + 1E-6f;
- freq_err_hz = cargf(freq_err_rect) * OFDM_RS / (TAU * Ns);
+ freq_err_hz = cargf(freq_err_rect) * Rs / (TAU * Ns);
ofdm->foff_est_hz += (ofdm->foff_est_gain * freq_err_hz);
}
ofdm->aphase_est_pilot_log[(rr * Nc) + (i - 1)] = aphase_est_pilot[i];
- if (OFDM_BPS == 1) {
+ if (Bps == 1) {
rx_bits[bit_index++] = crealf(rx_corr) > 0.0f;
- } else if (OFDM_BPS == 2) {
+ } else if (Bps == 2) {
/*
* Only one final task, decode what quadrant the phase
* is in, and return the dibits
#include <stdint.h>
#include "codec2_ofdm.h"
+#include "kiss_fft.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846f /* math constant */
#define TAU (2.0f * M_PI) /* mathematical constant */
-#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 /* Symbols per frame (number of rows incl pilot) */
-#define OFDM_CENTRE 1500.0f /* Center frequency */
+//#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 /* Symbols per frame (number of rows incl pilot) */
+//#define OFDM_CENTRE 1500.0f /* Center frequency */
/* To prevent C99 warning */
-#define OFDM_M 144 /* Samples per bare symbol (?) */
-#define OFDM_NCP 16 /* Samples per cyclic prefix */
-
-#ifdef OLD_STYLE
-/* This will produce a warning in C99 as (int) makes these variable */
-
-#define OFDM_M ((int)(OFDM_FS / OFDM_RS))
-#define OFDM_NCP ((int)(OFDM_TCP * OFDM_FS))
-#endif
-
-/* ? */
-#define OFDM_FTWINDOWWIDTH 11
-/* Bits per frame (duh) */
-#define OFDM_BITSPERFRAME ((OFDM_NS - 1) * (OFDM_NCX * OFDM_BPS))
-/* Rows per frame */
-#define OFDM_ROWSPERFRAME (OFDM_BITSPERFRAME / (OFDM_NCX * OFDM_BPS))
-/* Samps per frame */
-#define OFDM_SAMPLESPERFRAME (OFDM_NS * (OFDM_M + OFDM_NCP))
-
-#define OFDM_MAX_SAMPLESPERFRAME (OFDM_SAMPLESPERFRAME + (OFDM_M + OFDM_NCP)/4)
-#define OFDM_RXBUF (3 * OFDM_SAMPLESPERFRAME + 3 * (OFDM_M + OFDM_NCP))
+//#define OFDM_M 144 /* Samples per bare symbol (?) */
+//#define OFDM_NCP 16 /* Samples per cyclic prefix */
+//
+//#ifdef OLD_STYLE
+///* This will produce a warning in C99 as (int) makes these variable */
+//
+//#define OFDM_M ((int)(OFDM_FS / OFDM_RS))
+//#define OFDM_NCP ((int)(OFDM_TCP * OFDM_FS))
+//#endif
+
+///* ? */
+//#define OFDM_FTWINDOWWIDTH 11
+///* Bits per frame (duh) */
+//#define OFDM_BITSPERFRAME ((OFDM_NS - 1) * (OFDM_NCX * OFDM_BPS))
+///* Rows per frame */
+//#define OFDM_ROWSPERFRAME (OFDM_BITSPERFRAME / (OFDM_NCX * OFDM_BPS))
+///* Samps per frame */
+//#define OFDM_SAMPLESPERFRAME (OFDM_NS * (OFDM_M + OFDM_NCP))
+//
+//#define OFDM_MAX_SAMPLESPERFRAME (OFDM_SAMPLESPERFRAME + (OFDM_M + OFDM_NCP)/4)
+//#define OFDM_RXBUF (3 * OFDM_SAMPLESPERFRAME + 3 * (OFDM_M + OFDM_NCP))
/* Dummy struct for now, will contain constant configuration for OFDM modem */
struct OFDM_CONFIG{
int32_t Nc;
- int32_t Ts;
- int32_t Rs;
+ float Ts;
+ float Rs;
int32_t Fs;
int32_t bps;
int32_t Tcp;
complex float * pilot_samples;
complex float * rxbuf;
float * w;
-
+ kiss_fft_cfg sync_fft_cfg;
/* Demodulator data */