*/
static const char pilotvalues[] = {
-1, -1, 1, 1, -1, -1, -1, 1, -1,
- 1, -1, 1, 1, 1, 1, 1, 1, 1
+ 1, -1, 1, 1, 1, 1, 1, 1, 1,
+ 1
};
/* Functions */
float av_level = 2.0f * sqrtf(ofdm->timing_norm * acc / length) + 1E-12f;
for (i = 0; i < Ncorr; i++) {
- complex float temp = 0.0f + 0.0f * I;
+ complex float corr_st = 0.0f + 0.0f * I;
+ complex float corr_en = 0.0f + 0.0f * I;
for (j = 0; j < (OFDM_M + OFDM_NCP); j++) {
csam = conjf(ofdm->pilot_samples[j]);
- temp = temp + (rx[i + j] * csam);
- temp = temp + (rx[i + j + SFrame] * csam);
+ corr_st = corr_st + (rx[i + j] * csam);
+ corr_en = corr_en + (rx[i + j + SFrame] * csam);
}
- corr[i] = cabsf(temp) / av_level;
+ corr[i] = (cabsf(corr_st) + cabsf(corr_en)) / av_level;
}
/* find the max magnitude and its index */
for (i = 0; i < (OFDM_NC + 2); i++) {
aframe[0][i] = ofdm->pilots[i];
+ //printf("%2d % f % f\n", i, crealf(aframe[0][i]), cimagf(aframe[0][i]));
}
-
+
/* Place symbols in multi-carrier frame with pilots */
/* This will place boundary values of complex zero around data */
for (j = 1; j < (OFDM_NC + 1); j++) {
aframe[i][j] = tx_sym_lin[((i - 1) * OFDM_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)) {
idft(ofdm, asymbol, aframe[i]);
- /* Copy the last Ncp columns to the front */
+ /* Copy the last Ncp samples to the front */
for (j = (OFDM_M - OFDM_NCP), k = 0; j < OFDM_M; j++, k++) {
asymbol_cp[k] = asymbol[j];
}
- /* Now copy the whole row after it */
+ /* Now copy the all samples for this row after it */
for (j = OFDM_NCP, k = 0; k < OFDM_M; j++, k++) {
asymbol_cp[j] = asymbol[k];
}
- /* Now move row to the tx reference */
+ /* Now move row to the tx output */
for (j = 0; j < (OFDM_M + OFDM_NCP); j++) {
tx[m + j] = asymbol_cp[j];
/* store complex BPSK pilot symbols */
+ assert(sizeof(pilotvalues) == (OFDM_NC+2));
for (i = 0; i < (OFDM_NC + 2); i++) {
ofdm->pilots[i] = ((float) pilotvalues[i]) + 0.0f * I;
}
/* carrier tables for up and down conversion */
- float lower = OFDM_CENTRE - OFDM_RS * (OFDM_NC / 2);
- int Nlower = floorf(lower / OFDM_RS);
-
+ float alower = OFDM_CENTRE - OFDM_RS * ((float)OFDM_NC / 2);
+ int Nlower = floorf(alower / OFDM_RS);
+
for (i = 0, n = Nlower; i < (OFDM_NC + 2); i++, n++) {
float w = (TAU * (float) n) / (OFDM_FS / OFDM_RS);
-
for (j = 0; j < OFDM_M; j++) {
ofdm->W[i][j] = cexpf(I * w * j);
}
ofdm->foff_est_en = true;
ofdm->phase_est_en = true;
- ofdm->foff_est_gain = 0.01f;
+ ofdm->foff_est_gain = 0.05f;
ofdm->foff_est_hz = 0.0f;
ofdm->sample_point = 0;
ofdm->timing_est = 0;
complex float aphase_est_pilot_rect;
float aphase_est_pilot[OFDM_NC + 2];
float aamp_est_pilot[OFDM_NC + 2];
- float freq_err_hz, coarse_foff_est;
+ float freq_err_hz;
int i, j, k, rr, st, en, ft_est;
/* shift the buffer left based on nin */
}
if (ofdm->uw_errors > 2) {
ofdm->sync_counter++;
- }
- if (ofdm->sync_counter == sync_counter_thresh) {
- strcpy(next_state, "searching");
+ if (ofdm->sync_counter == sync_counter_thresh) {
+ strcpy(next_state, "searching");
+ }
} else {
ofdm->sync_counter = 0;
}
#include "octave.h"
#include "test_bits_ofdm.h"
-#define ASCALE (2E5*1.1491/2.0) /* scale from shorts back to floats */
-#define NFRAMES 100 /* just log the first 100 frames */
+#define ASCALE (2E5*1.1491/2.0) /* scale from shorts back to floats */
+#define NFRAMES 100 /* just log the first 100 frames */
+#define NDISCARD 20
int opt_exists(char *argv[], int argc, char opt[]) {
int i;
int timing_est_log[NFRAMES];
int i, j, f, oct, logframes, arg, sd;
-
+ int Nerrs, Terrs, Tbits, Terrs2, Tbits2, testframes, frame_count;
+
if (argc < 3) {
fprintf(stderr, "\n");
- printf("usage: %s InputModemRawFile OutputFile [-o OctaveLogFile] [--sd]\n", argv[0]);
+ printf("usage: %s InputModemRawFile OutputFile [-o OctaveLogFile] [--sd] [-v VerboseLevel]\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, " Default output file format is one byte per bit hard decision\n");
+ fprintf(stderr, " -t Receive test frames and count errors\n");
+ fprintf(stderr, " -v Verbose info the stderr\n");
fprintf(stderr, " -o Octave log file for testing\n");
fprintf(stderr, " --sd soft decision output, four doubles per QPSK symbol\n");
fprintf(stderr, "\n");
sd = 1;
}
+ testframes = 0;
+ if (opt_exists(argv, argc, "-t")) {
+ testframes = 1;
+ }
+
ofdm = ofdm_create(OFDM_CONFIG_700D);
assert(ofdm != NULL);
+ if ((arg = opt_exists(argv, argc, "-v")) != 0) {
+ ofdm_set_verbose(ofdm, atoi(argv[arg+1]));
+ }
+
int Nbitsperframe = ofdm_get_bits_per_frame(ofdm);
int Nmaxsamperframe = ofdm_get_max_samples_per_frame();
COMP rxbuf_in[Nmaxsamperframe];
int rx_bits[Nbitsperframe];
char rx_bits_char[Nbitsperframe];
- int state, next_state;
-
- state = OFDM_SEARCHING;
- f = 0;
+ int rx_uw[OFDM_UW_LEN];
+ f = 0; Nerrs = Terrs = Tbits = Terrs2 = Tbits2 = frame_count = 0;
nin_frame = ofdm_get_nin(ofdm);
while(fread(rx_scaled, sizeof(short), nin_frame, fin) == nin_frame) {
rxbuf_in[i].imag = 0.0;
}
- next_state = state;
- switch(state) {
- case OFDM_SEARCHING:
- if (ofdm_sync_search(ofdm, rxbuf_in)) {
- next_state = OFDM_SYNCED;
- }
- break;
- case OFDM_SYNCED:
- ofdm_demod(ofdm, rx_bits, rxbuf_in);
- break;
+ if (strcmp(ofdm->sync_state,"searching") == 0) {
+ ofdm_sync_search(ofdm, rxbuf_in);
}
- state = next_state;
+
+ if ((strcmp(ofdm->sync_state,"synced") == 0) || (strcmp(ofdm->sync_state,"trial_sync") == 0) ) {
+ ofdm_demod(ofdm, rx_bits, rxbuf_in);
+
+ if (sd == 0) {
+ /* simple hard decision output for uncoded testing */
+ for(i=0; i<Nbitsperframe; i++) {
+ rx_bits_char[i] = rx_bits[i];
+ }
+ fwrite(rx_bits_char, sizeof(char), Nbitsperframe, fout);
+ }
- nin_frame = ofdm_get_nin(ofdm);
+ /* extract Unique Word bits */
- if ((sd == 0) && (state == OFDM_SYNCED)) {
- /* simple hard decision output for uncoded testing */
- for(i=0; i<Nbitsperframe; i++) {
- rx_bits_char[i] = rx_bits[i];
+ for(i=0; i<OFDM_UW_LEN; i++) {
+ rx_uw[i] = rx_bits[i];
}
- fwrite(rx_bits_char, sizeof(char), Nbitsperframe, fout);
+
+ /* optional error counting in testframe mode */
+
+ if (testframes) {
+ Nerrs = 0;
+ for(i=0; i<Nbitsperframe; i++) {
+ if (test_bits_ofdm[i] != rx_bits[i]) {
+ Nerrs++;
+ }
+ }
+
+ Terrs += Nerrs;
+ Tbits += Nbitsperframe;
+
+ if (frame_count >= NDISCARD) {
+ Terrs2 += Nerrs;
+ Tbits2 += Nbitsperframe;
+ }
+ }
+ frame_count++;
+ }
+
+ nin_frame = ofdm_get_nin(ofdm);
+ ofdm_sync_state_machine(ofdm, rx_uw);
+
+ /* act on any events returned by state machine */
+
+ if (ofdm->sync_start) {
+ Terrs = Tbits = Terrs2 = Tbits2 = frame_count = 0;
}
+ if (ofdm->verbose) {
+ fprintf(stderr, "f: %2d state: %-10s uw_errors: %2d %1d Nerrs: %3d foff: %3.1f\n",
+ f, ofdm->last_sync_state, ofdm->uw_errors, ofdm->sync_counter, Nerrs, ofdm->foff_est_hz);
+ }
+
+ /* optional logging of states */
+
if (oct) {
/* note corrected phase (rx no phase) is one big linear array for frame */
fclose(fin);
fclose(fout);
+ if (testframes) {
+ fprintf(stderr, "BER..: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs/Tbits, Tbits, Terrs);
+ fprintf(stderr, "BER2.: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs2/Tbits2, Tbits2, Terrs2);
+ }
+
/* optionally dump Octave files */
if (foct != NULL) {
#include "test_bits_ofdm.h"
#define LOG_FRAMES 100
+#define NDISCARD 20
int opt_exists(char *argv[], int argc, char opt[]) {
int i;
int main(int argc, char *argv[])
{
FILE *fin;
- int i, f, Nerrs, Terrs, Tbits, verbose;
+ int i, f, Nerrs, Terrs, Tbits, Terrs2, Tbits2, verbose;
float aber;
struct OFDM *ofdm;
int Nbitsperframe = ofdm_get_bits_per_frame(ofdm);
char rx_bits[Nbitsperframe];
- f = Terrs = Tbits = 0;
+ f = Terrs = Tbits = Terrs2 = Tbits2 = 0;
while (fread(rx_bits, sizeof(char), Nbitsperframe, fin) == Nbitsperframe) {
f++;
}
aber = (float)Nerrs/Nbitsperframe;
- if (aber < 0.2) {
- Terrs += Nerrs;
- Tbits += Nbitsperframe;
- }
+ Terrs += Nerrs;
+ Tbits += Nbitsperframe;
+ if (f >= NDISCARD) {
+ Terrs2 += Nerrs;
+ Tbits2 += Nbitsperframe;
+ }
+
if (verbose) {
printf("f: %d Nerrs: %d aber: %3.2f\n", f, Nerrs, aber);
}
fclose(fin);
fprintf(stderr, "BER..: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs/Tbits, Tbits, Terrs);
+ fprintf(stderr, "BER2.: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs2/Tbits2, Tbits2, Terrs2);
return 0;
}