From 7d1b89550e3bc863a0ba94f6d8b11dade0252991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niccol=C3=B2=20Izzo?= Date: Thu, 14 Apr 2022 10:51:27 +0200 Subject: [PATCH] Rewrite quantization algorithm Quantization algorithm is now based on separate rolling averages for positive and negative samples. Merged csv outputs from syncword search and quantization on Linux. TG-81 --- .../include/protocols/M17/M17Demodulator.h | 8 ++- openrtx/src/protocols/M17/M17Demodulator.cpp | 67 +++++++++++-------- scripts/plot_m17_demod_csv.py | 16 +++-- scripts/plot_m17_demod_csv3.py | 15 ----- scripts/plot_m17_demod_csv4.py | 15 ----- 5 files changed, 55 insertions(+), 66 deletions(-) delete mode 100755 scripts/plot_m17_demod_csv3.py delete mode 100755 scripts/plot_m17_demod_csv4.py diff --git a/openrtx/include/protocols/M17/M17Demodulator.h b/openrtx/include/protocols/M17/M17Demodulator.h index 072ca2da..38229a6d 100644 --- a/openrtx/include/protocols/M17/M17Demodulator.h +++ b/openrtx/include/protocols/M17/M17Demodulator.h @@ -124,8 +124,8 @@ private: static constexpr size_t M17_BRIDGE_SIZE = M17_SAMPLES_PER_SYMBOL * M17_SYNCWORD_SYMBOLS; static constexpr float CONV_STATS_ALPHA = 0.001f; - static constexpr float QNT_STATS_ALPHA = 0.999f; static constexpr float CONV_THRESHOLD_FACTOR = 3.40; + static constexpr int16_t QNT_SMA_WINDOW = 40; /** * M17 syncwords; @@ -164,8 +164,10 @@ private: /* * Quantization statistics computation */ - float qnt_max = 0.0f; ///< Max hold of the sliced samples - float qnt_min = 0.0f; ///< Min hold of the sliced samples. + std::deque qnt_pos_fifo; + std::deque qnt_neg_fifo; + float qnt_pos_avg = 0.0f; ///< Rolling average of positive samples + float qnt_neg_avg = 0.0f; ///< Rolling average of negative samples /* * DSP filter state diff --git a/openrtx/src/protocols/M17/M17Demodulator.cpp b/openrtx/src/protocols/M17/M17Demodulator.cpp index d36dea86..fc9a1f44 100644 --- a/openrtx/src/protocols/M17/M17Demodulator.cpp +++ b/openrtx/src/protocols/M17/M17Demodulator.cpp @@ -66,11 +66,8 @@ void M17Demodulator::init() newFrame = false; #ifdef PLATFORM_LINUX - FILE *csv_log = fopen("demod_log_1.csv", "w"); - fprintf(csv_log, "Signal,Convolution,Threshold,Offset\n"); - fclose(csv_log); - csv_log = fopen("demod_log_2.csv", "w"); - fprintf(csv_log, "Sample,Max,Min,Symbol,I\n"); + FILE *csv_log = fopen("demod_log.csv", "w"); + fprintf(csv_log, "Signal,Convolution,Threshold,Offset,Sample,Max,Min,Symbol,I\n"); fclose(csv_log); #endif // PLATFORM_MOD17 } @@ -124,8 +121,8 @@ float M17Demodulator::getCorrelationStddev() void M17Demodulator::resetQuantizationStats() { - qnt_max = 0.0f; - qnt_min = 0.0f; + qnt_pos_avg = 0.0f; + qnt_neg_avg = 0.0f; } void M17Demodulator::updateQuantizationStats(int32_t offset) @@ -136,14 +133,28 @@ void M17Demodulator::updateQuantizationStats(int32_t offset) sample = basebandBridge[M17_BRIDGE_SIZE + offset]; else // Otherwise use regular data buffer sample = baseband.data[offset]; - if (sample > qnt_max) - qnt_max = sample; + if (sample > 0) + { + // If the FIFO is not full just push a new sample + if (qnt_pos_fifo.size() >= QNT_SMA_WINDOW) + { + qnt_pos_avg += 1 / static_cast(QNT_SMA_WINDOW) * + (sample - qnt_pos_fifo.back()); + qnt_pos_fifo.pop_back(); + } + qnt_pos_fifo.push_front(sample); + } else - qnt_max *= QNT_STATS_ALPHA; - if (sample < qnt_min) - qnt_min = sample; - else - qnt_min *= QNT_STATS_ALPHA; + { + // If the FIFO is not full just push a new sample + if (qnt_neg_fifo.size() >= QNT_SMA_WINDOW) + { + qnt_neg_avg += 1 / static_cast(QNT_SMA_WINDOW) * + (sample - qnt_neg_fifo.back()); + qnt_neg_fifo.pop_back(); + } + qnt_neg_fifo.push_front(sample); + } } int32_t M17Demodulator::convolution(int32_t offset, @@ -169,7 +180,7 @@ int32_t M17Demodulator::convolution(int32_t offset, sync_t M17Demodulator::nextFrameSync(int32_t offset) { #ifdef PLATFORM_LINUX - FILE *csv_log = fopen("demod_log_1.csv", "a"); + FILE *csv_log = fopen("demod_log.csv", "a"); #endif sync_t syncword = { -1, false }; @@ -192,11 +203,12 @@ sync_t M17Demodulator::nextFrameSync(int32_t offset) else // Otherwise use regular data buffer sample = baseband.data[i]; - fprintf(csv_log, "%" PRId16 ",%d,%f,%d\n", + fprintf(csv_log, "%" PRId16 ",%d,%f,%d,%" PRId16 ",%f,%f,%d,%d\n", sample, - conv, - CONV_THRESHOLD_FACTOR * getCorrelationStddev(), - i); + conv / 10, + CONV_THRESHOLD_FACTOR * getCorrelationStddev() / 10, + i, + 0,0.0,0.0,0,0); #endif // Positive correlation peak -> frame syncword @@ -226,9 +238,9 @@ int8_t M17Demodulator::quantize(int32_t offset) sample = basebandBridge[M17_BRIDGE_SIZE + offset]; else // Otherwise use regular data buffer sample = baseband.data[offset]; - if (sample > static_cast< int16_t >(qnt_max) / 2) + if (sample > static_cast< int16_t >(qnt_pos_avg)) return +3; - else if (sample < static_cast< int16_t >(qnt_min) / 2) + else if (sample < static_cast< int16_t >(qnt_neg_avg)) return -3; else if (sample > 0) return +1; @@ -271,7 +283,7 @@ bool M17Demodulator::update() dsp_dcRemoval(&dsp_state, baseband.data, baseband.len); #ifdef PLATFORM_LINUX - FILE *csv_log = fopen("demod_log_2.csv", "a"); + FILE *csv_log = fopen("demod_log.csv", "a"); #endif if(baseband.data != NULL) @@ -314,12 +326,13 @@ bool M17Demodulator::update() int8_t symbol = quantize(symbol_index); #ifdef PLATFORM_LINUX - fprintf(csv_log, "%" PRId16 ",%f,%f,%d,%d\n", - baseband.data[symbol_index] - (int16_t) qnt_ema, - qnt_max / 2, - qnt_min / 2, + fprintf(csv_log, "%" PRId16 ",%d,%f,%d,%" PRId16 ",%f,%f,%d,%d\n", + 0,0,0.0,0, + baseband.data[symbol_index], + qnt_pos_avg, + qnt_neg_avg, symbol * 666, - frameIndex == 0 ? 2300 : symbol_index); + frameIndex); #endif setSymbol(*activeFrame, frameIndex, symbol); diff --git a/scripts/plot_m17_demod_csv.py b/scripts/plot_m17_demod_csv.py index 24b2c726..89d0e9f7 100755 --- a/scripts/plot_m17_demod_csv.py +++ b/scripts/plot_m17_demod_csv.py @@ -6,11 +6,15 @@ from sys import argv plt.rcParams["figure.autolayout"] = True df = pd.read_csv(argv[1]) -#df = df.head(n=10000) print("Contents in csv file:\n", df) -#plt.plot(df.index, df.Input) -#plt.plot(df.index, df.RRCSignal) -plt.plot(df.index, df.LSFConvolution) -plt.plot(df.index, df.FrameConvolution) -plt.plot(df.index, df.Stddev) +plt.plot(df.index, df.Signal) +plt.plot(df.index, df.Convolution) +plt.plot(df.index, df.Threshold) +plt.plot(df.index, df.Threshold * -1) +plt.plot(df.index, df.Offset) +plt.plot(df.index, df.Sample) +plt.plot(df.index, df.Max) +plt.plot(df.index, df.Min) +#plt.plot(df.index, df.Symbol) +plt.plot(df.index, df.I) plt.show() diff --git a/scripts/plot_m17_demod_csv3.py b/scripts/plot_m17_demod_csv3.py deleted file mode 100755 index 1c7b9d9a..00000000 --- a/scripts/plot_m17_demod_csv3.py +++ /dev/null @@ -1,15 +0,0 @@ -#! /usr/bin/env python3 - -import pandas as pd -from matplotlib import pyplot as plt -from sys import argv - -plt.rcParams["figure.autolayout"] = True -df = pd.read_csv(argv[1]) -print("Contents in csv file:\n", df) -plt.plot(df.index, df.Signal) -plt.plot(df.index, df.Convolution) -plt.plot(df.index, df.Threshold) -plt.plot(df.index, df.Threshold * -1) -plt.plot(df.index, df.Offset) -plt.show() diff --git a/scripts/plot_m17_demod_csv4.py b/scripts/plot_m17_demod_csv4.py deleted file mode 100755 index 7a864d67..00000000 --- a/scripts/plot_m17_demod_csv4.py +++ /dev/null @@ -1,15 +0,0 @@ -#! /usr/bin/env python3 - -import pandas as pd -from matplotlib import pyplot as plt -from sys import argv - -plt.rcParams["figure.autolayout"] = True -df = pd.read_csv(argv[1]) -print("Contents in csv file:\n", df) -plt.plot(df.index, df.Sample) -plt.plot(df.index, df.Max) -plt.plot(df.index, df.Min) -plt.plot(df.index, df.Symbol) -plt.plot(df.index, df.I) -plt.show()