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
This commit is contained in:
parent
aa9fcc26b7
commit
7d1b89550e
|
|
@ -124,8 +124,8 @@ private:
|
||||||
static constexpr size_t M17_BRIDGE_SIZE = M17_SAMPLES_PER_SYMBOL * M17_SYNCWORD_SYMBOLS;
|
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 CONV_STATS_ALPHA = 0.001f;
|
||||||
static constexpr float QNT_STATS_ALPHA = 0.999f;
|
|
||||||
static constexpr float CONV_THRESHOLD_FACTOR = 3.40;
|
static constexpr float CONV_THRESHOLD_FACTOR = 3.40;
|
||||||
|
static constexpr int16_t QNT_SMA_WINDOW = 40;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* M17 syncwords;
|
* M17 syncwords;
|
||||||
|
|
@ -164,8 +164,10 @@ private:
|
||||||
/*
|
/*
|
||||||
* Quantization statistics computation
|
* Quantization statistics computation
|
||||||
*/
|
*/
|
||||||
float qnt_max = 0.0f; ///< Max hold of the sliced samples
|
std::deque<int16_t> qnt_pos_fifo;
|
||||||
float qnt_min = 0.0f; ///< Min hold of the sliced samples.
|
std::deque<int16_t> 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
|
* DSP filter state
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,8 @@ void M17Demodulator::init()
|
||||||
newFrame = false;
|
newFrame = false;
|
||||||
|
|
||||||
#ifdef PLATFORM_LINUX
|
#ifdef PLATFORM_LINUX
|
||||||
FILE *csv_log = fopen("demod_log_1.csv", "w");
|
FILE *csv_log = fopen("demod_log.csv", "w");
|
||||||
fprintf(csv_log, "Signal,Convolution,Threshold,Offset\n");
|
fprintf(csv_log, "Signal,Convolution,Threshold,Offset,Sample,Max,Min,Symbol,I\n");
|
||||||
fclose(csv_log);
|
|
||||||
csv_log = fopen("demod_log_2.csv", "w");
|
|
||||||
fprintf(csv_log, "Sample,Max,Min,Symbol,I\n");
|
|
||||||
fclose(csv_log);
|
fclose(csv_log);
|
||||||
#endif // PLATFORM_MOD17
|
#endif // PLATFORM_MOD17
|
||||||
}
|
}
|
||||||
|
|
@ -124,8 +121,8 @@ float M17Demodulator::getCorrelationStddev()
|
||||||
|
|
||||||
void M17Demodulator::resetQuantizationStats()
|
void M17Demodulator::resetQuantizationStats()
|
||||||
{
|
{
|
||||||
qnt_max = 0.0f;
|
qnt_pos_avg = 0.0f;
|
||||||
qnt_min = 0.0f;
|
qnt_neg_avg = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void M17Demodulator::updateQuantizationStats(int32_t offset)
|
void M17Demodulator::updateQuantizationStats(int32_t offset)
|
||||||
|
|
@ -136,14 +133,28 @@ void M17Demodulator::updateQuantizationStats(int32_t offset)
|
||||||
sample = basebandBridge[M17_BRIDGE_SIZE + offset];
|
sample = basebandBridge[M17_BRIDGE_SIZE + offset];
|
||||||
else // Otherwise use regular data buffer
|
else // Otherwise use regular data buffer
|
||||||
sample = baseband.data[offset];
|
sample = baseband.data[offset];
|
||||||
if (sample > qnt_max)
|
if (sample > 0)
|
||||||
qnt_max = sample;
|
{
|
||||||
|
// 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<float>(QNT_SMA_WINDOW) *
|
||||||
|
(sample - qnt_pos_fifo.back());
|
||||||
|
qnt_pos_fifo.pop_back();
|
||||||
|
}
|
||||||
|
qnt_pos_fifo.push_front(sample);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
qnt_max *= QNT_STATS_ALPHA;
|
{
|
||||||
if (sample < qnt_min)
|
// If the FIFO is not full just push a new sample
|
||||||
qnt_min = sample;
|
if (qnt_neg_fifo.size() >= QNT_SMA_WINDOW)
|
||||||
else
|
{
|
||||||
qnt_min *= QNT_STATS_ALPHA;
|
qnt_neg_avg += 1 / static_cast<float>(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,
|
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)
|
sync_t M17Demodulator::nextFrameSync(int32_t offset)
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_LINUX
|
#ifdef PLATFORM_LINUX
|
||||||
FILE *csv_log = fopen("demod_log_1.csv", "a");
|
FILE *csv_log = fopen("demod_log.csv", "a");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sync_t syncword = { -1, false };
|
sync_t syncword = { -1, false };
|
||||||
|
|
@ -192,11 +203,12 @@ sync_t M17Demodulator::nextFrameSync(int32_t offset)
|
||||||
else // Otherwise use regular data buffer
|
else // Otherwise use regular data buffer
|
||||||
sample = baseband.data[i];
|
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,
|
sample,
|
||||||
conv,
|
conv / 10,
|
||||||
CONV_THRESHOLD_FACTOR * getCorrelationStddev(),
|
CONV_THRESHOLD_FACTOR * getCorrelationStddev() / 10,
|
||||||
i);
|
i,
|
||||||
|
0,0.0,0.0,0,0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Positive correlation peak -> frame syncword
|
// Positive correlation peak -> frame syncword
|
||||||
|
|
@ -226,9 +238,9 @@ int8_t M17Demodulator::quantize(int32_t offset)
|
||||||
sample = basebandBridge[M17_BRIDGE_SIZE + offset];
|
sample = basebandBridge[M17_BRIDGE_SIZE + offset];
|
||||||
else // Otherwise use regular data buffer
|
else // Otherwise use regular data buffer
|
||||||
sample = baseband.data[offset];
|
sample = baseband.data[offset];
|
||||||
if (sample > static_cast< int16_t >(qnt_max) / 2)
|
if (sample > static_cast< int16_t >(qnt_pos_avg))
|
||||||
return +3;
|
return +3;
|
||||||
else if (sample < static_cast< int16_t >(qnt_min) / 2)
|
else if (sample < static_cast< int16_t >(qnt_neg_avg))
|
||||||
return -3;
|
return -3;
|
||||||
else if (sample > 0)
|
else if (sample > 0)
|
||||||
return +1;
|
return +1;
|
||||||
|
|
@ -271,7 +283,7 @@ bool M17Demodulator::update()
|
||||||
dsp_dcRemoval(&dsp_state, baseband.data, baseband.len);
|
dsp_dcRemoval(&dsp_state, baseband.data, baseband.len);
|
||||||
|
|
||||||
#ifdef PLATFORM_LINUX
|
#ifdef PLATFORM_LINUX
|
||||||
FILE *csv_log = fopen("demod_log_2.csv", "a");
|
FILE *csv_log = fopen("demod_log.csv", "a");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(baseband.data != NULL)
|
if(baseband.data != NULL)
|
||||||
|
|
@ -314,12 +326,13 @@ bool M17Demodulator::update()
|
||||||
int8_t symbol = quantize(symbol_index);
|
int8_t symbol = quantize(symbol_index);
|
||||||
|
|
||||||
#ifdef PLATFORM_LINUX
|
#ifdef PLATFORM_LINUX
|
||||||
fprintf(csv_log, "%" PRId16 ",%f,%f,%d,%d\n",
|
fprintf(csv_log, "%" PRId16 ",%d,%f,%d,%" PRId16 ",%f,%f,%d,%d\n",
|
||||||
baseband.data[symbol_index] - (int16_t) qnt_ema,
|
0,0,0.0,0,
|
||||||
qnt_max / 2,
|
baseband.data[symbol_index],
|
||||||
qnt_min / 2,
|
qnt_pos_avg,
|
||||||
|
qnt_neg_avg,
|
||||||
symbol * 666,
|
symbol * 666,
|
||||||
frameIndex == 0 ? 2300 : symbol_index);
|
frameIndex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setSymbol<M17_FRAME_BYTES>(*activeFrame, frameIndex, symbol);
|
setSymbol<M17_FRAME_BYTES>(*activeFrame, frameIndex, symbol);
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,15 @@ from sys import argv
|
||||||
|
|
||||||
plt.rcParams["figure.autolayout"] = True
|
plt.rcParams["figure.autolayout"] = True
|
||||||
df = pd.read_csv(argv[1])
|
df = pd.read_csv(argv[1])
|
||||||
#df = df.head(n=10000)
|
|
||||||
print("Contents in csv file:\n", df)
|
print("Contents in csv file:\n", df)
|
||||||
#plt.plot(df.index, df.Input)
|
plt.plot(df.index, df.Signal)
|
||||||
#plt.plot(df.index, df.RRCSignal)
|
plt.plot(df.index, df.Convolution)
|
||||||
plt.plot(df.index, df.LSFConvolution)
|
plt.plot(df.index, df.Threshold)
|
||||||
plt.plot(df.index, df.FrameConvolution)
|
plt.plot(df.index, df.Threshold * -1)
|
||||||
plt.plot(df.index, df.Stddev)
|
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()
|
plt.show()
|
||||||
|
|
|
||||||
|
|
@ -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()
|
|
||||||
|
|
@ -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()
|
|
||||||
Loading…
Reference in New Issue