aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--src/DabModulator.cpp4
-rw-r--r--src/SignalMultiplexer.cpp14
-rw-r--r--src/TII.cpp297
-rw-r--r--src/TII.h72
5 files changed, 386 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index 5c7c60b..5f73f3b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -165,6 +165,8 @@ odr_dabmod_SOURCES = src/DabMod.cpp \
src/FormatConverter.h \
src/Utils.cpp \
src/Utils.h \
+ src/TII.cpp \
+ src/TII.h \
src/zmq.hpp
dist_bin_SCRIPTS = src/crc-dwap.py
diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp
index 667d885..94b6c87 100644
--- a/src/DabModulator.cpp
+++ b/src/DabModulator.cpp
@@ -46,6 +46,7 @@
#include "Resampler.h"
#include "ConvEncoder.h"
#include "FIRFilter.h"
+#include "TII.h"
#include "PuncturingEncoder.h"
#include "TimeInterleaver.h"
#include "TimestampDecoder.h"
@@ -197,6 +198,8 @@ int DabModulator::process(Buffer* const dataIn, Buffer* dataOut)
cic_ratio));
+ shared_ptr<TII> tii(new TII(myDabMode, 3, 16));
+
shared_ptr<OfdmGenerator> cifOfdm(
new OfdmGenerator((1 + myNbSymbols), myNbCarriers, mySpacing));
@@ -346,6 +349,7 @@ int DabModulator::process(Buffer* const dataIn, Buffer* dataOut)
myFlowgraph->connect(cifFreq, cifDiff);
myFlowgraph->connect(cifNull, cifSig);
myFlowgraph->connect(cifDiff, cifSig);
+ myFlowgraph->connect(tii, cifSig);
if (useCicEq) {
myFlowgraph->connect(cifSig, cifCicEq);
myFlowgraph->connect(cifCicEq, cifOfdm);
diff --git a/src/SignalMultiplexer.cpp b/src/SignalMultiplexer.cpp
index c5be552..8edcdc2 100644
--- a/src/SignalMultiplexer.cpp
+++ b/src/SignalMultiplexer.cpp
@@ -46,6 +46,7 @@ SignalMultiplexer::~SignalMultiplexer()
// dataIn[0] -> null symbol
// dataIn[1] -> MSC symbols
+// dataIn[2] -> (optional) TII symbol
int SignalMultiplexer::process(std::vector<Buffer*> dataIn, Buffer* dataOut)
{
#ifdef DEBUG
@@ -60,10 +61,17 @@ int SignalMultiplexer::process(std::vector<Buffer*> dataIn, Buffer* dataOut)
fprintf(stderr, ", dataOut: %p, sizeOut: %zu)\n", dataOut, dataOut->getLength());
#endif
- assert(dataIn.size() == 2);
+ assert(dataIn.size() == 2 or dataIn.size() == 3);
- *dataOut = *dataIn[0];
- *dataOut += *dataIn[1];
+ if (dataIn.size() == 2) {
+ *dataOut = *dataIn[0];
+ *dataOut += *dataIn[1];
+ }
+ else if (dataIn.size() == 3) {
+ *dataOut = *dataIn[2];
+ *dataOut += *dataIn[1];
+ }
return dataOut->getLength();
}
+
diff --git a/src/TII.cpp b/src/TII.cpp
new file mode 100644
index 0000000..9ccc6e0
--- /dev/null
+++ b/src/TII.cpp
@@ -0,0 +1,297 @@
+/*
+ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty
+ the Queen in Right of Canada (Communications Research Center Canada)
+
+ Copyright (C) 2015
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://opendigitalradio.org
+ */
+/*
+ This file is part of ODR-DabMod.
+
+ ODR-DabMod is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ ODR-DabMod 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "TII.h"
+#include "PcDebug.h"
+
+#include <stdio.h>
+#include <stdexcept>
+#include <string.h>
+
+typedef std::complex<float> complexf;
+
+/* TII pattern for TM I, II, IV */
+const int pattern_tm1_2_4[][8] = { // {{{
+ {0,0,0,0,1,1,1,1},
+ {0,0,0,1,0,1,1,1},
+ {0,0,0,1,1,0,1,1},
+ {0,0,0,1,1,1,0,1},
+ {0,0,0,1,1,1,1,0},
+ {0,0,1,0,0,1,1,1},
+ {0,0,1,0,1,0,1,1},
+ {0,0,1,0,1,1,0,1},
+ {0,0,1,0,1,1,1,0},
+ {0,0,1,1,0,0,1,1},
+ {0,0,1,1,0,1,0,1},
+ {0,0,1,1,0,1,1,0},
+ {0,0,1,1,1,0,0,1},
+ {0,0,1,1,1,0,1,0},
+ {0,0,1,1,1,1,0,0},
+ {0,1,0,0,0,1,1,1},
+ {0,1,0,0,1,0,1,1},
+ {0,1,0,0,1,1,0,1},
+ {0,1,0,0,1,1,1,0},
+ {0,1,0,1,0,0,1,1},
+ {0,1,0,1,0,1,0,1},
+ {0,1,0,1,0,1,1,0},
+ {0,1,0,1,1,0,0,1},
+ {0,1,0,1,1,0,1,0},
+ {0,1,0,1,1,1,0,0},
+ {0,1,1,0,0,0,1,1},
+ {0,1,1,0,0,1,0,1},
+ {0,1,1,0,0,1,1,0},
+ {0,1,1,0,1,0,0,1},
+ {0,1,1,0,1,0,1,0},
+ {0,1,1,0,1,1,0,0},
+ {0,1,1,1,0,0,0,1},
+ {0,1,1,1,0,0,1,0},
+ {0,1,1,1,0,1,0,0},
+ {0,1,1,1,1,0,0,0},
+ {1,0,0,0,0,1,1,1},
+ {1,0,0,0,1,0,1,1},
+ {1,0,0,0,1,1,0,1},
+ {1,0,0,0,1,1,1,0},
+ {1,0,0,1,0,0,1,1},
+ {1,0,0,1,0,1,0,1},
+ {1,0,0,1,0,1,1,0},
+ {1,0,0,1,1,0,0,1},
+ {1,0,0,1,1,0,1,0},
+ {1,0,0,1,1,1,0,0},
+ {1,0,1,0,0,0,1,1},
+ {1,0,1,0,0,1,0,1},
+ {1,0,1,0,0,1,1,0},
+ {1,0,1,0,1,0,0,1},
+ {1,0,1,0,1,0,1,0},
+ {1,0,1,0,1,1,0,0},
+ {1,0,1,1,0,0,0,1},
+ {1,0,1,1,0,0,1,0},
+ {1,0,1,1,0,1,0,0},
+ {1,0,1,1,1,0,0,0},
+ {1,1,0,0,0,0,1,1},
+ {1,1,0,0,0,1,0,1},
+ {1,1,0,0,0,1,1,0},
+ {1,1,0,0,1,0,0,1},
+ {1,1,0,0,1,0,1,0},
+ {1,1,0,0,1,1,0,0},
+ {1,1,0,1,0,0,0,1},
+ {1,1,0,1,0,0,1,0},
+ {1,1,0,1,0,1,0,0},
+ {1,1,0,1,1,0,0,0},
+ {1,1,1,0,0,0,0,1},
+ {1,1,1,0,0,0,1,0},
+ {1,1,1,0,0,1,0,0},
+ {1,1,1,0,1,0,0,0},
+ {1,1,1,1,0,0,0,0} }; // }}}
+
+
+TII::TII(unsigned int dabmode, unsigned int comb, unsigned int pattern) :
+ ModCodec(ModFormat(0), ModFormat(0)),
+ m_dabmode(dabmode),
+ m_comb(comb),
+ m_pattern(pattern),
+ m_insert(true)
+{
+ PDEBUG("TII::TII(%u) @ %p\n", dabmode, this);
+
+ std::stringstream ss;
+ ss << "TII(comb:" << m_comb << ", pattern:" << m_pattern << ")";
+ m_name = ss.str();
+
+ switch (m_dabmode) {
+ case 1:
+ m_carriers = 1536;
+
+ if (not(0 <= m_pattern and m_pattern <= 69) ) {
+ throw std::runtime_error(
+ "TII::TII pattern not valid!");
+ }
+ break;
+ case 2:
+ m_carriers = 384;
+
+ if (not(0 <= m_pattern and m_pattern <= 69) ) {
+ throw std::runtime_error(
+ "TII::TII pattern not valid!");
+ }
+ break;
+ /* unsupported
+ case 3:
+ m_carriers = 192;
+ break;
+ case 4:
+ d_dabmode = 0;
+ case 0:
+ */
+ default:
+ std::stringstream ss_exception;
+ ss_exception <<
+ "TII::TII DAB mode " << m_dabmode << " not valid!";
+ throw std::runtime_error(ss_exception.str());
+ }
+
+ if (not(0 < m_comb and m_comb <= 23) ) {
+ throw std::runtime_error(
+ "TII::TII comb not valid!");
+ }
+
+ m_dataIn.clear();
+ m_dataIn.resize(m_carriers);
+ prepare_pattern();
+
+ myOutputFormat.size(m_carriers * sizeof(complexf));
+}
+
+
+TII::~TII()
+{
+ PDEBUG("TII::~TII() @ %p\n", this);
+}
+
+
+int TII::process(Buffer* const dataIn, Buffer* dataOut)
+{
+ PDEBUG("TII::process(dataIn: %p, dataOut: %p)\n",
+ dataIn, dataOut);
+
+ if ((dataIn != NULL) && (dataIn->getLength() != 0)) {
+ throw std::runtime_error(
+ "TII::process input size not valid!");
+ }
+
+ if (m_insert) {
+ dataOut->setData(&m_dataIn[0], m_carriers * sizeof(complexf));
+ }
+ else {
+ dataOut->setLength(m_carriers * sizeof(complexf));
+ bzero(dataOut->getData(), dataOut->getLength());
+ }
+
+ // TODO wrong! Must align with frames containing the right data
+ m_insert = not m_insert;
+
+ return 1;
+}
+
+void TII::enable_carrier(int k) {
+ fprintf(stderr, "k = %d\n", k);
+
+ int ix = m_carriers/2 + k;
+
+ if (ix < 0 or ix > (ssize_t)m_dataIn.size()) {
+ throw std::runtime_error(
+ "TII::enable_carrier invalid k!");
+ }
+
+ m_dataIn[ix] = 1.0; // TODO power of the carrier ?
+}
+
+void TII::prepare_pattern() {
+ int comb = m_comb; // Convert from unsigned to signed
+
+ // This could be written more efficiently, but since it is
+ // not performance-critial, it makes sense to write it
+ // in the same way as the specification in
+ // ETSI EN 300 401 Clause 14.8
+ if (m_dabmode == 1) {
+ for (int k = -768; k < -384; k++) {
+ for (int b = 0; b < 8; b++) {
+ if ( k == -768 + 2 * comb + 48 * b and
+ pattern_tm1_2_4[m_pattern][b]) {
+ enable_carrier(k);
+ enable_carrier(k+1);
+ }
+ }
+ }
+
+ for (int k = -384; k < -0; k++) {
+ for (int b = 0; b < 8; b++) {
+ if ( k == -384 + 2 * comb + 48 * b and
+ pattern_tm1_2_4[m_pattern][b]) {
+ enable_carrier(k);
+ enable_carrier(k+1);
+ }
+ }
+ }
+
+ for (int k = 1; k <= 384; k++) {
+ for (int b = 0; b < 8; b++) {
+ if ( k == 1 + 2 * comb + 48 * b and
+ pattern_tm1_2_4[m_pattern][b]) {
+ enable_carrier(k);
+ enable_carrier(k+1);
+ }
+ }
+ }
+
+ for (int k = 384; k <= 768; k++) {
+ for (int b = 0; b < 8; b++) {
+ if ( k == 385 + 2 * comb + 48 * b and
+ pattern_tm1_2_4[m_pattern][b]) {
+ enable_carrier(k);
+ enable_carrier(k+1);
+ }
+ }
+ }
+ }
+ else if (m_dabmode == 2) {
+ for (int k = -192; k <= 192; k++) {
+ for (int b = 0; b < 4; b++) {
+ if ( k == -192 + 2 * comb + 48 * b and
+ pattern_tm1_2_4[m_pattern][b]) {
+ enable_carrier(k);
+ enable_carrier(k+1);
+ }
+ }
+
+ for (int b = 4; b < 8; b++) {
+ if ( k == -191 + 2 * comb + 48 * b and
+ pattern_tm1_2_4[m_pattern][b]) {
+ enable_carrier(k);
+ enable_carrier(k+1);
+ }
+ }
+ }
+ }
+ else {
+ throw std::runtime_error(
+ "TII::TII DAB mode not valid!");
+ }
+
+
+}
+
+#ifdef TII_TEST
+int main(int argc, char** argv)
+{
+ const unsigned int mode = 2;
+ const unsigned int comb = 4;
+ const unsigned int pattern = 16;
+ TII tii(mode, comb, pattern);
+
+ return 0;
+}
+#endif
+
diff --git a/src/TII.h b/src/TII.h
new file mode 100644
index 0000000..44f37ce
--- /dev/null
+++ b/src/TII.h
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty
+ the Queen in Right of Canada (Communications Research Center Canada)
+
+ Copyright (C) 2015
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://opendigitalradio.org
+ */
+/*
+ This file is part of ODR-DabMod.
+
+ ODR-DabMod is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ ODR-DabMod 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TII_H
+#define TII_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ModCodec.h"
+
+#include <sys/types.h>
+#include <complex>
+#include <vector>
+#include <string>
+
+class TII : public ModCodec
+{
+ public:
+ TII(unsigned int dabmode, unsigned int comb, unsigned int pattern);
+ virtual ~TII();
+
+ int process(Buffer* const dataIn, Buffer* dataOut);
+ const char* name() { return m_name.c_str(); };
+
+ protected:
+ unsigned int m_dabmode;
+ unsigned int m_comb;
+ unsigned int m_pattern;
+
+ bool m_insert;
+
+ size_t m_carriers;
+
+ std::string m_name;
+ std::vector<std::complex<float> > m_dataIn;
+
+ void prepare_pattern(void);
+
+ void enable_carrier(int k);
+
+ private:
+ TII(const TII&);
+ TII& operator=(const TII&);
+};
+
+#endif // TII_H
+