From 183e3bfc6c5f3f1bb4e9640bfa44fb2e3dc16cbe Mon Sep 17 00:00:00 2001
From: Glenn Bradford <glenn.bradford@unimelb.edu.au>
Date: Fri, 8 Apr 2022 19:57:38 +1000
Subject: [PATCH] fix tx rrc scaling, add cfo command and time/chan est tags

---
 examples/packet_phy_tx.grc          |  2 +-
 grc/elen90089_corr_est_cc.block.yml |  6 +++-
 lib/corr_est_cc_impl.cc             | 52 ++++++++++++++++++++---------
 lib/corr_est_cc_impl.h              |  1 +
 python/packet_phy_tx.py             |  2 +-
 5 files changed, 45 insertions(+), 18 deletions(-)

diff --git a/examples/packet_phy_tx.grc b/examples/packet_phy_tx.grc
index 7d6128c..e91a642 100644
--- a/examples/packet_phy_tx.grc
+++ b/examples/packet_phy_tx.grc
@@ -108,7 +108,7 @@ blocks:
   parameters:
     alpha: excess_bw
     comment: ''
-    gain: nfilts/2
+    gain: nfilts
     ntaps: 5*sps*nfilts
     samp_rate: nfilts
     sym_rate: '1.0'
diff --git a/grc/elen90089_corr_est_cc.block.yml b/grc/elen90089_corr_est_cc.block.yml
index fa8de8c..4db7551 100644
--- a/grc/elen90089_corr_est_cc.block.yml
+++ b/grc/elen90089_corr_est_cc.block.yml
@@ -19,11 +19,15 @@ inputs:
 - label: in
   domain: stream
   dtype: complex
+
 outputs:
 - label: out
   domain: stream
   dtype: complex
-- label: out
+- label: cfo
+  domain: message
+  optional: True
+- label: corr
   domain: stream
   dtype: float
   optional: True
diff --git a/lib/corr_est_cc_impl.cc b/lib/corr_est_cc_impl.cc
index 5cb25a7..cd9e757 100644
--- a/lib/corr_est_cc_impl.cc
+++ b/lib/corr_est_cc_impl.cc
@@ -36,6 +36,8 @@ corr_est_cc_impl::corr_est_cc_impl(const std::vector<gr_complex>& sequence,
 {
     set_max_noutput_items(s_nitems);
     set_sequence(sequence);
+
+    message_port_register_out(pmt::mp("cfo"));
 }
 
 corr_est_cc_impl::~corr_est_cc_impl() {}
@@ -54,14 +56,14 @@ void corr_est_cc_impl::set_sequence(const std::vector<gr_complex>& sequence)
     // create time-reversed conjugate of training sequence for filtering
     std::vector<gr_complex> taps(sequence.size());
     std::reverse_copy(sequence.begin(), sequence.end(), taps.begin()); 
-    float scale = 0.0;
+    d_scale = 0.0;
     for (size_t i = 0; i < taps.size(); i++) {
         taps[i] = std::conj(taps[i]);
-        scale += std::norm(taps[i]);
+        d_scale += std::norm(taps[i]);
     }
-    scale = 1.0 / sqrt(scale);
+    d_scale = 1.0 / sqrt(d_scale);
     for (size_t i = 0; i < taps.size(); i++) {
-        taps[i] *= scale;
+        taps[i] *= d_scale;
     }
 
     // set taps and block output multiple to FFT kernel's internal nsamples
@@ -150,25 +152,45 @@ int corr_est_cc_impl::work(int noutput_items,
         if (corr_mag[i] > d_threshold) {
             // coarse frequency estimate
             double freq_est = estimate_freq_offset(&in[i]);
+            
+            // single-tap (inverse) channel estimate
+            gr_complex chan_est = d_corr[i] * d_scale;
+            chan_est = conj(chan_est) / (chan_est*conj(chan_est));
+            
+            // time phase estimate - center-of-mass (3 samples)
+            double nom = corr_mag[i-1] + 2*corr_mag[i] + 3*corr_mag[i+1];
+            double den = corr_mag[i-1] +   corr_mag[i] +   corr_mag[i+1];
+            double time_est = (nom/den) - 2.0;
+
+            // send frequency correction message
+            int offset = nitems_written(0) + i;
+            pmt::pmt_t cmd = pmt::make_dict();
+            cmd = pmt::dict_add(cmd,
+                                pmt::mp("offset"),
+                                pmt::from_long(offset)); 
+            cmd = pmt::dict_add(cmd,
+                                pmt::mp("inc"),
+                                pmt::from_double(-freq_est));
+            message_port_pub(pmt::mp("cfo"), cmd);
 
             // tag output
-            add_item_tag(0, nitems_written(0) + i,
-                         pmt::intern("corr_start"),
-                         pmt::from_double(corr_mag[i]),
-                         d_src_id);
-            add_item_tag(0, nitems_written(0) + i,
-                         pmt::intern("freq_est"),
-                         pmt::from_double(freq_est),
-                         d_src_id);
-            if (output_items.size() > 1) {
-                add_item_tag(1, nitems_written(0) + i,
+            for(int ch = 0; ch < output_items.size(); ch++) {
+                add_item_tag(ch, offset,
                              pmt::intern("corr_start"),
                              pmt::from_double(corr_mag[i]),
                              d_src_id);
-                add_item_tag(1, nitems_written(0) + i,
+                add_item_tag(ch, offset,
                              pmt::intern("freq_est"),
                              pmt::from_double(freq_est),
                              d_src_id);
+                add_item_tag(ch, offset,
+                             pmt::intern("chan_est"),
+                             pmt::from_complex(chan_est),
+                             d_src_id);
+                add_item_tag(ch, offset,
+                             pmt::intern("time_est"),
+                             pmt::from_double(time_est),
+                             d_src_id);
             }
 
             // skip remaining symbols in sequence
diff --git a/lib/corr_est_cc_impl.h b/lib/corr_est_cc_impl.h
index 9fc44e6..479dac5 100644
--- a/lib/corr_est_cc_impl.h
+++ b/lib/corr_est_cc_impl.h
@@ -28,6 +28,7 @@ private:
     volk::vector<gr_complex> d_corr;
     volk::vector<float> d_corr_mag;
     volk::vector<float> d_y_mag;
+    float d_scale;
     float d_y_accum;
     int d_skip;
 
diff --git a/python/packet_phy_tx.py b/python/packet_phy_tx.py
index ce7df6e..831abba 100644
--- a/python/packet_phy_tx.py
+++ b/python/packet_phy_tx.py
@@ -43,7 +43,7 @@ class packet_phy_tx(gr.hier_block2):
         # Variables
         ##################################################
         self.nfilts = nfilts = 32
-        self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts/2, nfilts,1.0, excess_bw, 5*sps*nfilts)
+        self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts,1.0, excess_bw, 5*sps*nfilts)
         self.taps_per_filt = taps_per_filt = len(rrc_taps)/nfilts
         self.header_format_cdc_0 = header_format_cdc_0 = elen90089.header_format_cdc(digital.packet_utils.default_access_code, 3, 1)
         self.hdr_encoder = hdr_encoder = fec.dummy_encoder_make(1500)
-- 
GitLab