aboutsummaryrefslogtreecommitdiffstats
path: root/src/sdr
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2011-12-16 14:09:19 +0100
committerSylvain Munaut <tnt@246tNt.com>2011-12-16 14:11:16 +0100
commit80e0aabf91d4f90b462fed62db3831007cdb51f3 (patch)
tree668fafaacf69b2577f103eaeb5eb243606ea16aa /src/sdr
parent240dfdf22f5f691a18e4c7bfb2dcdfdcdb52b3ed (diff)
sdr/dkab: Add support for Dual Keep Alive Bursts demodulation
The actual data out of the demodulation is not tested tough since the upper layers can't handle that yet. Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Diffstat (limited to 'src/sdr')
-rw-r--r--src/sdr/Makefile.am2
-rw-r--r--src/sdr/dkab.c190
2 files changed, 191 insertions, 1 deletions
diff --git a/src/sdr/Makefile.am b/src/sdr/Makefile.am
index b2edef9..0d92d22 100644
--- a/src/sdr/Makefile.am
+++ b/src/sdr/Makefile.am
@@ -4,4 +4,4 @@ AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOSDR_LIBS) $(FFTW3F_LIBS)
noinst_LIBRARIES = libgmr1-sdr.a
-libgmr1_sdr_a_SOURCES = fcch.c nb.c pi4cxpsk.c
+libgmr1_sdr_a_SOURCES = dkab.c fcch.c nb.c pi4cxpsk.c
diff --git a/src/sdr/dkab.c b/src/sdr/dkab.c
new file mode 100644
index 0000000..265d254
--- /dev/null
+++ b/src/sdr/dkab.c
@@ -0,0 +1,190 @@
+/* GMR-1 SDR - DKABs bursts */
+/* See GMR-1 05.004 (ETSI TS 101 376-5-4 V1.2.1) - Section 6.1
+ * GMR-1 05.002 (ETSI TS 101 376-5-2 V1.1.1) - Section 7.4.6 */
+
+/* (C) 2011 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \addtogroup dkab
+ * @{
+ */
+
+/*! \file sdr/dkab.c
+ * \brief Osmocom GMR-1 DKABs bursts implementation
+ */
+
+#include <complex.h>
+#include <math.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <osmocom/core/bits.h>
+
+#include <osmocom/sdr/cxvec.h>
+#include <osmocom/sdr/cxvec_math.h>
+
+#include <osmocom/gmr1/sdr/defs.h>
+#include <osmocom/gmr1/sdr/dkab.h>
+
+
+/*! \brief Finds the precise TOA of a DKAB burts by looking for power spikes
+ * \param[in] burst Complex signal of the burst
+ * \param[in] sps Oversampling used in the input complex signal
+ * \param[in] p DKAB position
+ * \param[out] toa_p Pointer to TOA return variable
+ * \returns 0 for success. -errno for errors
+ */
+static int
+_gmr1_dkab_find_toa(struct osmo_cxvec *burst, int sps, int p, float *toa_p)
+{
+ struct osmo_cxvec *pwr = NULL;
+ int w, i, ofs[2], d, mi;
+ float mp, toa;
+
+ /* Window size */
+ w = burst->len - (GMR1_DKAB_SYMS * sps) + 1;
+ if (w <= 0)
+ return -EINVAL;
+
+ /* Energy vector */
+ pwr = osmo_cxvec_alloc(w);
+ if (!pwr)
+ return -ENOMEM;
+
+ ofs[0] = sps * (2 + p); /* First KAB position */
+ ofs[1] = sps * (2 + p + 59); /* Second KAB position */
+ d = sps * 5; /* Length of KAB */
+
+ pwr->data[0] = 0.0f;
+
+ for (i=0; i<d; i++) {
+ pwr->data[0] +=
+ osmo_normsqf(burst->data[ofs[0]+i]) +
+ osmo_normsqf(burst->data[ofs[1]+i]);
+ }
+
+ mi = 0; /* Max index */
+ mp = pwr->data[0]; /* Max pwr */
+
+ for (i=0; i<w-1; i++)
+ {
+ float np;
+
+ np = pwr->data[i]
+ - osmo_normsqf(burst->data[ofs[0]+i])
+ - osmo_normsqf(burst->data[ofs[1]+i])
+ + osmo_normsqf(burst->data[ofs[0]+d+i])
+ + osmo_normsqf(burst->data[ofs[1]+d+i]);
+
+ pwr->data[i+1] = np;
+
+ if (np > mp) {
+ mi = i+1;
+ mp = np;
+ }
+ }
+
+ pwr->len = w;
+
+ /* Weigh & center peak */
+ toa = (float)mi;
+ if ((mi > 0) && (mi < (w-1)))
+ toa += 0.5f * (-pwr->data[mi-1] + pwr->data[mi+1]) /
+ (-pwr->data[mi-1] + 2.0f * pwr->data[mi] - pwr->data[mi+1]);
+ toa += ((float)(sps-1)) / 2.0f;
+
+ *toa_p = toa;
+
+ /* Done */
+ osmo_cxvec_free(pwr);
+
+ return 0;
+}
+
+/*! \brief Converts a burst into softbits given proper TOA
+ * \param[in] burst Complex signal of the burst
+ * \param[in] sps Oversampling used in the input complex signal
+ * \param[in] p DKAB position
+ * \param[in] toa The TOA to use to extract symbols
+ * \param[out] ebits Encoded soft bits return array
+ * \returns 0 for success. -errno for errors
+ */
+static int
+_gmr1_dkab_soft_bits(struct osmo_cxvec *burst, int sps, int p, float toa,
+ sbit_t *ebits)
+{
+ int i, toa_i, ofs[2], o;
+ float pd;
+
+ toa_i = (int)roundf(toa);
+ ofs[0] = toa_i + sps * (2 + p); /* First DKAB */
+ ofs[1] = toa_i + sps * (2 + p + 159); /* Second DKAB */
+
+ for (i=0; i<8; i++) {
+ o = ofs[i>>2] + (i&3);
+ pd = cargf(burst->data[o] * conjf(burst->data[o+sps]));
+ ebits[i] = (sbit_t)roundf((0.5f - (fabsf(pd) / M_PIf)) * 254.0f);
+ }
+
+ return 0;
+}
+
+/*! \brief All-in-one finding and demodulation of DKAB bursts
+ * \param[in] burst_in Complex signal of the burst
+ * \param[in] sps Oversampling used in the input complex signal
+ * \param[in] freq_shift Frequency shift to pre-apply to burst_in (rad/sym)
+ * \param[in] p DKAB position
+ * \param[out] ebits Encoded soft bits return array
+ * \param[out] toa_p Pointer to TOA return variable
+ * \returns 0 for success. -errno for errors
+ *
+ * burst_in is expected to be longer than necessary. Any extra length will be
+ * used as 'search window' to find proper alignement. Good practice is to have
+ * a few samples too much in front and a few samples after the expected TOA.
+ */
+int
+gmr1_dkab_demod(struct osmo_cxvec *burst_in, int sps, float freq_shift, int p,
+ sbit_t *ebits, float *toa_p)
+{
+ struct osmo_cxvec *burst = NULL;
+ int rv;
+
+ /* Normalize the burst and counter rotate by pi/4 */
+ burst = osmo_cxvec_sig_normalize(burst_in, 1, (freq_shift - (M_PIf/4)) / sps, NULL);
+ if (!burst) {
+ rv = -ENOMEM;
+ goto err;
+ }
+
+ /* Find TOA */
+ rv = _gmr1_dkab_find_toa(burst, sps, p, toa_p);
+ if (rv)
+ goto err;
+
+ /* Demodulate into soft bits */
+ rv = _gmr1_dkab_soft_bits(burst, sps, p, *toa_p, ebits);
+
+ /* Done */
+err:
+ osmo_cxvec_free(burst);
+
+ return rv;
+}
+
+/*! }@ */