summaryrefslogtreecommitdiff
path: root/gr-digital/lib/corr_est_cc_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gr-digital/lib/corr_est_cc_impl.cc')
-rw-r--r--gr-digital/lib/corr_est_cc_impl.cc81
1 files changed, 54 insertions, 27 deletions
diff --git a/gr-digital/lib/corr_est_cc_impl.cc b/gr-digital/lib/corr_est_cc_impl.cc
index 772fc780dc..5157f8f6de 100644
--- a/gr-digital/lib/corr_est_cc_impl.cc
+++ b/gr-digital/lib/corr_est_cc_impl.cc
@@ -55,6 +55,17 @@ namespace gr {
{
d_sps = sps;
+ // In order to easily support the optional second output,
+ // don't deal with an unbounded max number of output items.
+ // For the common case of not using the optional second output,
+ // this ensures we optimally call the volk routines.
+ const size_t nitems = 24*1024;
+ set_max_noutput_items(nitems);
+ d_corr = (gr_complex *)
+ volk_malloc(sizeof(gr_complex)*nitems, volk_get_alignment());
+ d_corr_mag = (float *)
+ volk_malloc(sizeof(float)*nitems, volk_get_alignment());
+
// Create time-reversed conjugate of symbols
d_symbols = symbols;
for(size_t i=0; i < d_symbols.size(); i++) {
@@ -96,16 +107,7 @@ namespace gr {
// volk_get_alignment() / sizeof(gr_complex);
//set_alignment(std::max(1,alignment_multiple));
- // In order to easily support the optional second output,
- // don't deal with an unbounded max number of output items.
- // For the common case of not using the optional second output,
- // this ensures we optimally call the volk routines.
- const size_t nitems = 24*1024;
- set_max_noutput_items(nitems);
- d_corr = (gr_complex *)
- volk_malloc(sizeof(gr_complex)*nitems, volk_get_alignment());
- d_corr_mag = (float *)
- volk_malloc(sizeof(float)*nitems, volk_get_alignment());
+ d_scale = 1.0f;
}
corr_est_cc_impl::~corr_est_cc_impl()
@@ -193,14 +195,7 @@ namespace gr {
corr_est_cc_impl::_set_threshold(float threshold)
{
d_stashed_threshold = threshold;
-
- // Compute a correlation threshold.
- // Compute the value of the discrete autocorrelation of the matched
- // filter with offset 0 (aka the autocorrelation peak).
- float corr = 0;
- for(size_t i = 0; i < d_symbols.size(); i++)
- corr += abs(d_symbols[i]*conj(d_symbols[i]));
- d_thresh = threshold*corr*corr;
+ d_pfa = -logf(1.0f-threshold);
}
void
@@ -228,10 +223,6 @@ namespace gr {
// Our correlation filter length
unsigned int hist_len = history() - 1;
- // Delay the output by our correlation filter length so we can
- // tag backwards in time
- memcpy(out, &in[0], sizeof(gr_complex)*noutput_items);
-
// Calculate the correlation of the non-delayed input with the
// known symbols.
d_filter->filter(noutput_items, &in[hist_len], corr);
@@ -239,19 +230,31 @@ namespace gr {
// Find the magnitude squared of the correlation
volk_32fc_magnitude_squared_32f(&d_corr_mag[0], corr, noutput_items);
+ float detection = 0;
+ for(int i = 0; i < noutput_items; i++) {
+ detection += d_corr_mag[i];
+ }
+ detection /= static_cast<float>(noutput_items);
+ detection *= d_pfa;
+
int isps = (int)(d_sps + 0.5f);
int i = 0;
while(i < noutput_items) {
- // Look for the correlator output to cross the threshold
- if (d_corr_mag[i] <= d_thresh) {
+ // Look for the correlator output to cross the threshold.
+ // Sum power over two consecutive symbols in case we're offset
+ // in time. If off by 1/2 a symbol, the peak of any one point
+ // is much lower.
+ float corr_mag = d_corr_mag[i] + d_corr_mag[i+1];
+ if(corr_mag <= 4*detection) {
i++;
continue;
}
+
// Go to (just past) the current correlator output peak
while ((i < (noutput_items-1)) &&
- (d_corr_mag[i] < d_corr_mag[i+1]))
+ (d_corr_mag[i] < d_corr_mag[i+1])) {
i++;
-
+ }
// Delaying the primary signal output by the matched filter
// length using history(), means that the the peak output of
// the matched filter aligns with the start of the desired
@@ -262,8 +265,9 @@ namespace gr {
add_item_tag(0, nitems_written(0) + i, pmt::intern("corr_start"),
pmt::from_double(d_corr_mag[i]), d_src_id);
+#if 0
// Use Parabolic interpolation to estimate a fractional
- // sample delay. There are more accurate methods as
+ // sample delay. There are more accurate methods as
// the sample delay estimate using this method is biased.
// But this method is simple and fast.
// center between [-0.5,0.5] units of samples
@@ -275,6 +279,21 @@ namespace gr {
double denom = 2*(d_corr_mag[i-1]-2*d_corr_mag[i]+d_corr_mag[i+1]);
center = nom/denom;
}
+#else
+ // Calculates the center of mass between the three points around the peak.
+ // Estimate is linear.
+ double nom = 0, den = 0;
+ nom = d_corr_mag[i-1] + 2*d_corr_mag[i] + 3*d_corr_mag[i+1];
+ den = d_corr_mag[i-1] + d_corr_mag[i] + d_corr_mag[i+1];
+ double center = nom / den;
+ center = (center - 2.0); // adjust for bias in center of mass calculation
+#endif
+
+ // Estimated scaling factor for the input stream to normalize
+ // the output to +/-1.
+ uint32_t maxi;
+ volk_32fc_index_max_32u_manual(&maxi, (gr_complex*)in, noutput_items, "generic");
+ d_scale = 1 / std::abs(in[maxi]);
// Calculate the phase offset of the incoming signal.
//
@@ -304,6 +323,8 @@ namespace gr {
// N.B. the appropriate d_corr_mag[] index is "i", not "index".
add_item_tag(0, nitems_written(0) + index, pmt::intern("corr_est"),
pmt::from_double(d_corr_mag[i]), d_src_id);
+ add_item_tag(0, nitems_written(0) + index, pmt::intern("amp_est"),
+ pmt::from_double(d_scale), d_src_id);
if (output_items.size() > 1) {
// N.B. these debug tags are not offset to avoid walking off out buf
@@ -313,6 +334,8 @@ namespace gr {
pmt::from_double(center), d_src_id);
add_item_tag(1, nitems_written(0) + i, pmt::intern("corr_est"),
pmt::from_double(d_corr_mag[i]), d_src_id);
+ add_item_tag(1, nitems_written(0) + i, pmt::intern("amp_est"),
+ pmt::from_double(d_scale), d_src_id);
}
// Skip ahead to the next potential symbol peak
@@ -325,6 +348,10 @@ namespace gr {
// pmt::intern("ce_eow"), pmt::from_uint64(noutput_items),
// d_src_id);
+ // Delay the output by our correlation filter length so we can
+ // tag backwards in time
+ memcpy(out, &in[0], sizeof(gr_complex)*noutput_items);
+
return noutput_items;
}