summaryrefslogtreecommitdiffstats
path: root/src/FrequencyInterleaver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/FrequencyInterleaver.cpp')
-rw-r--r--src/FrequencyInterleaver.cpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/FrequencyInterleaver.cpp b/src/FrequencyInterleaver.cpp
new file mode 100644
index 0000000..7930682
--- /dev/null
+++ b/src/FrequencyInterleaver.cpp
@@ -0,0 +1,131 @@
+/*
+ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty
+ the Queen in Right of Canada (Communications Research Center Canada)
+ */
+/*
+ This file is part of CRC-DADMOD.
+
+ CRC-DADMOD 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.
+
+ CRC-DADMOD 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 CRC-DADMOD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "FrequencyInterleaver.h"
+#include "PcDebug.h"
+
+#include <stdio.h>
+#include <stdexcept>
+#include <malloc.h>
+#include <complex>
+
+typedef std::complex<float> complexf;
+
+
+FrequencyInterleaver::FrequencyInterleaver(size_t mode) :
+ ModCodec(ModFormat(0), ModFormat(0))
+{
+ PDEBUG("FrequencyInterleaver::FrequencyInterleaver(%zu) @ %p\n",
+ mode, this);
+
+ size_t num;
+ size_t alpha = 13;
+ size_t beta;
+ switch (mode) {
+ case 1:
+ d_carriers = 1536;
+ num = 2048;
+ beta = 511;
+ break;
+ case 2:
+ d_carriers = 384;
+ num = 512;
+ beta = 127;
+ break;
+ case 3:
+ d_carriers = 192;
+ num = 256;
+ beta = 63;
+ break;
+ case 0:
+ case 4:
+ d_carriers = 768;
+ num = 1024;
+ beta = 255;
+ break;
+ default:
+ PDEBUG("Carriers: %zu\n", (d_carriers >> 1) << 1);
+ throw std::runtime_error("FrequencyInterleaver::FrequencyInterleaver "
+ "nb of carriers invalid!");
+ break;
+ }
+
+ d_indexes = (size_t*)memalign(16, d_carriers * sizeof(size_t));
+ size_t* index = d_indexes;
+ size_t perm = 0;
+ PDEBUG("i: %4u, R: %4u\n", 0, 0);
+ for (size_t j = 1; j < num; ++j) {
+ perm = (alpha * perm + beta) & (num - 1);
+ if (perm >= ((num - d_carriers) / 2)
+ && perm <= (num - (num - d_carriers) / 2)
+ && perm != (num / 2)) {
+ PDEBUG("i: %4zu, R: %4zu, d: %4zu, n: %4zu, k: %5zi, index: %zu\n",
+ j, perm, perm, index - d_indexes, perm - num / 2,
+ perm > num / 2
+ ? perm - (1 + (num / 2))
+ : perm + (d_carriers - (num / 2)));
+ *(index++) = perm > num / 2 ?
+ perm - (1 + (num / 2)) : perm + (d_carriers - (num / 2));
+ } else {
+ PDEBUG("i: %4zu, R: %4zu\n", j, perm);
+ }
+ }
+}
+
+
+FrequencyInterleaver::~FrequencyInterleaver()
+{
+ PDEBUG("FrequencyInterleaver::~FrequencyInterleaver() @ %p\n", this);
+
+ free(d_indexes);
+}
+
+
+int FrequencyInterleaver::process(Buffer* const dataIn, Buffer* dataOut)
+{
+ PDEBUG("FrequencyInterleaver::process"
+ "(dataIn: %p, sizeIn: %zu, dataOut: %p, sizeOut: %zu)\n",
+ dataIn, dataIn->getLength(), dataOut, dataOut->getLength());
+
+ dataOut->setLength(dataIn->getLength());
+
+ const complexf* in = reinterpret_cast<const complexf*>(dataIn->getData());
+ complexf* out = reinterpret_cast<complexf*>(dataOut->getData());
+ size_t sizeIn = dataIn->getLength() / sizeof(complexf);
+
+ if (sizeIn % d_carriers != 0) {
+ throw std::runtime_error(
+ "FrequencyInterleaver::process input size not valid!");
+ }
+
+ for (size_t i = 0; i < sizeIn;) {
+// memset(out, 0, d_carriers * sizeof(complexf));
+ for (size_t j = 0; j < d_carriers; i += 4, j += 4) {
+ out[d_indexes[j]] = in[i];
+ out[d_indexes[j + 1]] = in[i + 1];
+ out[d_indexes[j + 2]] = in[i + 2];
+ out[d_indexes[j + 3]] = in[i + 3];
+ }
+ out += d_carriers;
+ }
+
+ return 1;
+}