#include #include #include #include #include "freq_meas.h" #include "sr_global.h" #include "dsss_demod.h" #include "simulation.h" #include "generated/dsss_gold_code.h" /* Generated CWT wavelet LUT */ extern const float * const dsss_cwt_wavelet_table; struct iir_biquad cwt_filter_bq[3] = { {.a = {-1.993939440f, 0.993949280f}, .b = {0.2459934300683e-5, 0.4919868601367e-5, 0.2459934300683e-5}}, {.a = {-1.995557124f, 0.995566972f}, .b = {0.2461930046414e-5, 0.4923860092828e-5, 0.2461930046414e-5}}, {.a = {-1.998365254f, 0.998375115f}, .b = {0.2465394452097e-5, 0.4930788904195e-5, 0.2465394452097e-5}}, }; float gold_correlate_step(const size_t ncode, const float a[DSSS_CORRELATION_LENGTH], size_t offx); float cwt_convolve_step(const float v[DSSS_WAVELET_LUT_SIZE], size_t offx); float run_iir(const float x, const int order, const struct iir_biquad q[order], struct iir_biquad_state st[order]); float run_biquad(float x, const struct iir_biquad *const q, struct iir_biquad_state *const restrict st); #ifdef SIMULATION void dsss_demod_step(struct dsss_demod_state *st, float new_value, size_t sim_pos) { #else /* SIMULATION */ void dsss_demod_step(struct dsss_demod_state *st, float new_value) { #endif /* SIMULATION */ //#define DEBUG_PRINT(...) ((void)0) //#define DEBUG_PRINTN(...) ((void)0) bool debug = sim_pos % DSSS_CORRELATION_LENGTH == 0; if (debug) DEBUG_PRINT("Iteration %zd", sim_pos); //const float peak_group_threshold = 0.05 * DSSS_CORRELATION_LENGTH; //const float hole_patching_threshold = 0.01 * DSSS_CORRELATION_LENGTH; st->signal[st->signal_wpos] = new_value; st->signal_wpos = (st->signal_wpos + 1) % ARRAY_LENGTH(st->signal); if (debug) DEBUG_PRINT(" signal: %f", new_value); /* use new, incremented wpos for gold_correlate_step as first element of old data in ring buffer */ for (size_t i=0; icorrelation[i][st->correlation_wpos] = gold_correlate_step(i, st->signal, st->correlation_wpos); /* debug */ /* DEBUG_PRINTN(" correlation: ["); for (size_t i=0; icorrelation[i][st->correlation_wpos]); DEBUG_PRINTN("]\n"); */ /* end */ st->correlation_wpos = (st->correlation_wpos + 1) % ARRAY_LENGTH(st->correlation[0]); float cwt[DSSS_GOLD_CODE_COUNT]; for (size_t i=0; icorrelation[i], st->correlation_wpos); /* debug */ if (debug) DEBUG_PRINTN(" cwt: ["); for (size_t i=0; icwt_filter[i].st); /* debug */ /* DEBUG_PRINTN(" avg: ["); for (size_t i=0; igroup.max; int max_ch = st->group.max_ch; int max_idx = st->group.max_idx + 1; bool found = false; if (debug) DEBUG_PRINTN(" rel: ["); for (size_t i=0; i DSSS_THESHOLD_FACTOR) found = true; if (fabs(val) > fabs(max_val)) { max_val = val; max_ch = i; max_idx = st->group.len; } } if (debug) DEBUG_PRINTN("]\n"); /* debug */ if (debug) DEBUG_PRINT(" found=%d len=%d idx=%d ch=%d max=%f", found, st->group.len, st->group.max_idx, st->group.max_ch, st->group.max); /* end */ if (found) { /* Continue ongoing group */ st->group.len++; st->group.max = max_val; st->group.max_ch = max_ch; st->group.max_idx = max_idx; return; } if (st->group.len == 0) /* We're between groups */ return; /* A group ended. Process result. */ DEBUG_PRINT("GROUP FOUND: %8d len=%3d max=%f ch=%d offx=%d", sim_pos, st->group.len, st->group.max, st->group.max_ch, st->group.max_idx); /* reset grouping state */ st->group.len = 0; st->group.max_idx = 0; st->group.max_ch = 0; st->group.max = 0.0f; } float run_iir(const float x, const int order, const struct iir_biquad q[order], struct iir_biquad_state st[order]) { float intermediate = x; for (int i=0; i<(order+1)/2; i++) intermediate = run_biquad(intermediate, &q[i], &st[i]); return intermediate; } float run_biquad(float x, const struct iir_biquad *const q, struct iir_biquad_state *const restrict st) { /* direct form 2, see https://en.wikipedia.org/wiki/Digital_biquad_filter */ float intermediate = x + st->reg[0] * -q->a[0] + st->reg[1] * -q->a[1]; float out = intermediate * q->b[0] + st->reg[0] * q->b[1] + st->reg[1] * q->b[2]; st->reg[1] = st->reg[0]; st->reg[0] = intermediate; return out; } float cwt_convolve_step(const float v[DSSS_WAVELET_LUT_SIZE], size_t offx) { float sum = 0.0f; for (ssize_t j=0; j>3]; /* Fetch sequence table item */ int bv = table_byte & (1<<(pos&7)); /* Extract bit */ bv = !!bv*2 - 1; /* Map 0, 1 -> -1, 1 */ acc_inner += a[(offx + i + j) % DSSS_CORRELATION_LENGTH] * bv; /* Multiply item */ } acc_outer += acc_inner; } return acc_outer / DSSS_CORRELATION_LENGTH; }