summaryrefslogtreecommitdiffstats
path: root/src/PrbsGenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/PrbsGenerator.cpp')
-rw-r--r--src/PrbsGenerator.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/PrbsGenerator.cpp b/src/PrbsGenerator.cpp
new file mode 100644
index 0000000..1f8437c
--- /dev/null
+++ b/src/PrbsGenerator.cpp
@@ -0,0 +1,143 @@
+/*
+ Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right
+ of Canada (Communications Research Center Canada)
+ */
+/*
+ This file is part of ODR-DabMux.
+
+ ODR-DabMux 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-DabMux 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-DabMux. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "PrbsGenerator.h"
+
+#include <string.h>
+#include <limits.h>
+
+
+/*
+ * Generate a parity check for a 32-bit word.
+ */
+static uint32_t parity_check(uint32_t prbs_accum)
+{
+ uint32_t mask = 1;
+ uint32_t parity = 0;
+ for (int i = 0; i < 32; ++i) {
+ parity ^= ((prbs_accum & mask) != 0);
+ mask <<= 1;
+ }
+ return parity;
+}
+
+void PrbsGenerator::setup(uint32_t polynomial)
+{
+ this->polynomial = polynomial;
+ this->accum = 0;
+ gen_prbs_table();
+ gen_weight_table();
+}
+
+uint8_t PrbsGenerator::step()
+{
+ accum = update_prbs();
+ return accum & 0xff;
+}
+
+void PrbsGenerator::rewind()
+{
+ while (accum < polynomial) {
+ accum <<= 1;
+ accum |= 1;
+ }
+}
+
+void PrbsGenerator::gen_prbs_table()
+{
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < 256; ++j) {
+ uint32_t prbs_accum = ((uint32_t)j << (i * 8));
+ for (int k = 0; k < 8; ++k) {
+ prbs_accum = (prbs_accum << 1)
+ ^ parity_check(prbs_accum & polynomial);
+ }
+
+ prbs_table[i][j] = (prbs_accum & 0xff);
+ }
+ }
+}
+
+uint32_t PrbsGenerator::update_prbs()
+{
+ uint8_t acc_lsb = 0;
+ for (int i = 0; i < 4; ++i ) {
+ acc_lsb ^= prbs_table [i] [ (accum >> (i * 8) ) & 0xff ];
+ }
+ return (accum << 8) ^ ((uint32_t)acc_lsb);
+}
+
+void PrbsGenerator::gen_weight_table()
+{
+ for (int i = 0; i < 256; ++i) {
+ uint8_t mask = 1;
+ uint8_t ones_count = 0;
+
+ for (int j = 0; j < 8; ++j) {
+ ones_count += ((i & mask) != 0);
+ mask = mask << 1;
+ }
+ weight[i] = ones_count;
+ }
+}
+
+size_t PrbsGenerator::error_count(
+ uint8_t *rx_data,
+ size_t rx_data_length)
+{
+ uint32_t error_count = 0;
+ uint32_t prbs_accum = 0;
+
+ /* seed the PRBS accumulator */
+ for (int i = 0; i < 4; ++i) {
+ prbs_accum = (prbs_accum << 8) ^ (rx_data[i] ^ polarity_mask);
+ }
+
+ /* check the received data */
+ for (size_t i = 0; i < rx_data_length; ++i) {
+ uint8_t error_pattern =
+ (prbs_accum >> 24) ^ (rx_data[i] ^ polarity_mask);
+
+ if (error_pattern != 0) {
+ error_count += weight[error_pattern];
+ }
+ prbs_accum = update_prbs();
+ }
+ return error_count;
+}
+
+void PrbsGenerator::gen_sequence(
+ uint8_t *tx_data,
+ size_t tx_data_length,
+ uint32_t polynomial)
+{
+ uint32_t prbs_accum = 0;
+
+ while (prbs_accum < polynomial) {
+ prbs_accum <<= 1;
+ prbs_accum |= 1;
+ }
+
+ for (size_t i = 0; i < tx_data_length; i++) {
+ prbs_accum = update_prbs();
+ tx_data[i] = (uint8_t)(prbs_accum & 0xff);
+ }
+}