Removed a printf left behind after debugging from M17 demodulator class and slightly cleaned up the code
This commit is contained in:
parent
163a2ef06a
commit
54a89abcd0
|
|
@ -42,7 +42,8 @@ typedef struct
|
||||||
{
|
{
|
||||||
int32_t index;
|
int32_t index;
|
||||||
bool lsf;
|
bool lsf;
|
||||||
} sync_t;
|
}
|
||||||
|
sync_t;
|
||||||
|
|
||||||
class M17Demodulator
|
class M17Demodulator
|
||||||
{
|
{
|
||||||
|
|
@ -153,20 +154,15 @@ private:
|
||||||
/*
|
/*
|
||||||
* Convolution statistics computation
|
* Convolution statistics computation
|
||||||
*/
|
*/
|
||||||
float conv_ema = 0.0f;
|
float conv_ema = 0.0f; /// Exponential moving average from all the correlation values.
|
||||||
float conv_emvar = 0.0f;
|
float conv_emvar = 0.0f;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Quantization statistics computation
|
* Quantization statistics computation
|
||||||
*/
|
*/
|
||||||
float qnt_ema = 0.0f;
|
float qnt_ema = 0.0f; ///< Exponential moving average from of the sliced samples.
|
||||||
float qnt_max = 0.0f;
|
float qnt_max = 0.0f; ///< Max hold of the sliced samples
|
||||||
float qnt_min = 0.0f;
|
float qnt_min = 0.0f; ///< Min hold of the sliced samples.
|
||||||
|
|
||||||
/**
|
|
||||||
* Deque containing the sliced samples
|
|
||||||
*/
|
|
||||||
// std::deque<int16_t> samples_fifo;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the exponential mean and variance/stddev computation.
|
* Resets the exponential mean and variance/stddev computation.
|
||||||
|
|
@ -181,13 +177,6 @@ private:
|
||||||
*/
|
*/
|
||||||
void updateCorrelationStats(int32_t value);
|
void updateCorrelationStats(int32_t value);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the exponential moving average from all the correlation values.
|
|
||||||
*
|
|
||||||
* @returns float numerical value of the exponential moving average
|
|
||||||
*/
|
|
||||||
float getCorrelationEma();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the standard deviation from all the correlation values.
|
* Returns the standard deviation from all the correlation values.
|
||||||
*
|
*
|
||||||
|
|
@ -208,27 +197,6 @@ private:
|
||||||
*/
|
*/
|
||||||
void updateQuantizationStats(int32_t offset);
|
void updateQuantizationStats(int32_t offset);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the exponential moving average from of the sliced samples.
|
|
||||||
*
|
|
||||||
* @returns float numerical value of the exponential moving average
|
|
||||||
*/
|
|
||||||
float getQuantizationEma();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the max hold of the sliced samples.
|
|
||||||
*
|
|
||||||
* @returns float numerical value of the max hold
|
|
||||||
*/
|
|
||||||
float getQuantizationMax();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the min hold of the sliced samples.
|
|
||||||
*
|
|
||||||
* @returns float numerical value of the min hold
|
|
||||||
*/
|
|
||||||
float getQuantizationMin();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the convolution between a stride of samples starting from
|
* Computes the convolution between a stride of samples starting from
|
||||||
* a given offset and a target waveform.
|
* a given offset and a target waveform.
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,7 @@
|
||||||
#include <emulator.h>
|
#include <emulator.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace M17
|
using namespace M17;
|
||||||
{
|
|
||||||
|
|
||||||
M17Demodulator::M17Demodulator()
|
M17Demodulator::M17Demodulator()
|
||||||
{
|
{
|
||||||
|
|
@ -103,7 +102,7 @@ void M17Demodulator::stopBasebandSampling()
|
||||||
|
|
||||||
void M17Demodulator::resetCorrelationStats()
|
void M17Demodulator::resetCorrelationStats()
|
||||||
{
|
{
|
||||||
conv_ema = 0.0f;
|
conv_ema = 0.0f;
|
||||||
conv_emvar = 800000000.0f;
|
conv_emvar = 800000000.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,11 +118,6 @@ void M17Demodulator::updateCorrelationStats(int32_t value)
|
||||||
conv_emvar = (1.0f - conv_stats_alpha) * (conv_emvar + delta * incr);
|
conv_emvar = (1.0f - conv_stats_alpha) * (conv_emvar + delta * incr);
|
||||||
}
|
}
|
||||||
|
|
||||||
float M17Demodulator::getCorrelationEma()
|
|
||||||
{
|
|
||||||
return conv_ema;
|
|
||||||
}
|
|
||||||
|
|
||||||
float M17Demodulator::getCorrelationStddev()
|
float M17Demodulator::getCorrelationStddev()
|
||||||
{
|
{
|
||||||
return sqrt(conv_emvar);
|
return sqrt(conv_emvar);
|
||||||
|
|
@ -159,21 +153,6 @@ void M17Demodulator::updateQuantizationStats(int32_t offset)
|
||||||
qnt_min *= qnt_stats_alpha;
|
qnt_min *= qnt_stats_alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
float M17Demodulator::getQuantizationEma()
|
|
||||||
{
|
|
||||||
return qnt_ema;
|
|
||||||
}
|
|
||||||
|
|
||||||
float M17Demodulator::getQuantizationMax()
|
|
||||||
{
|
|
||||||
return qnt_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
float M17Demodulator::getQuantizationMin()
|
|
||||||
{
|
|
||||||
return qnt_min;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t M17Demodulator::convolution(int32_t offset,
|
int32_t M17Demodulator::convolution(int32_t offset,
|
||||||
int8_t *target,
|
int8_t *target,
|
||||||
size_t target_size)
|
size_t target_size)
|
||||||
|
|
@ -199,15 +178,14 @@ 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_1.csv", "a");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sync_t syncword = { -1, false };
|
sync_t syncword = { -1, false };
|
||||||
// Find peaks in the correlation between the baseband and the frame syncword
|
// Find peaks in the correlation between the baseband and the frame syncword
|
||||||
// Leverage the fact LSF syncword is the opposite of the frame syncword
|
// Leverage the fact LSF syncword is the opposite of the frame syncword
|
||||||
// to detect both syncwords at once. Stop early because convolution needs
|
// to detect both syncwords at once. Stop early because convolution needs
|
||||||
// access samples ahead of the starting offset.
|
// access samples ahead of the starting offset.
|
||||||
for(int32_t i = offset;
|
int32_t maxLen = static_cast < int32_t >(baseband.len - M17_BRIDGE_SIZE);
|
||||||
syncword.index == -1 &&
|
for(int32_t i = offset; (syncword.index == -1) && (i < maxLen); i++)
|
||||||
i < (int32_t) baseband.len - (int32_t) M17_BRIDGE_SIZE;
|
|
||||||
i++)
|
|
||||||
{
|
{
|
||||||
// If we are not locked search for a syncword
|
// If we are not locked search for a syncword
|
||||||
int32_t conv = convolution(i, stream_syncword, M17_SYNCWORD_SYMBOLS);
|
int32_t conv = convolution(i, stream_syncword, M17_SYNCWORD_SYMBOLS);
|
||||||
|
|
@ -218,28 +196,31 @@ sync_t M17Demodulator::nextFrameSync(int32_t offset)
|
||||||
sample = basebandBridge[M17_BRIDGE_SIZE + i];
|
sample = basebandBridge[M17_BRIDGE_SIZE + i];
|
||||||
else // Otherwise use regular data buffer
|
else // Otherwise use regular data buffer
|
||||||
sample = baseband.data[i];
|
sample = baseband.data[i];
|
||||||
|
|
||||||
#ifdef PLATFORM_LINUX
|
#ifdef PLATFORM_LINUX
|
||||||
fprintf(csv_log, "%" PRId16 ",%d,%f,%d\n",
|
fprintf(csv_log, "%" PRId16 ",%d,%f,%d\n",
|
||||||
sample,
|
sample,
|
||||||
conv - (int32_t) getCorrelationEma(),
|
conv - static_cast< int32_t >(conv_ema),
|
||||||
conv_threshold_factor * getCorrelationStddev(),
|
conv_threshold_factor * getCorrelationStddev(),
|
||||||
i);
|
i);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Positive correlation peak -> frame syncword
|
// Positive correlation peak -> frame syncword
|
||||||
if (conv - (int32_t) getCorrelationEma() >
|
if ((conv - static_cast< int32_t >(conv_ema)) >
|
||||||
getCorrelationStddev() * conv_threshold_factor)
|
(getCorrelationStddev() * conv_threshold_factor))
|
||||||
{
|
{
|
||||||
syncword.lsf = false;
|
syncword.lsf = false;
|
||||||
syncword.index = i;
|
syncword.index = i;
|
||||||
}
|
}
|
||||||
// Negative correlation peak -> LSF syncword
|
// Negative correlation peak -> LSF syncword
|
||||||
else if (conv - (int32_t) getCorrelationEma() <
|
else if ((conv - static_cast< int32_t >(conv_ema)) <
|
||||||
-(getCorrelationStddev() * conv_threshold_factor))
|
-(getCorrelationStddev() * conv_threshold_factor))
|
||||||
{
|
{
|
||||||
syncword.lsf = true;
|
syncword.lsf = true;
|
||||||
syncword.index = i;
|
syncword.index = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PLATFORM_LINUX
|
#ifdef PLATFORM_LINUX
|
||||||
fclose(csv_log);
|
fclose(csv_log);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -254,10 +235,10 @@ int8_t M17Demodulator::quantize(int32_t offset)
|
||||||
else // Otherwise use regular data buffer
|
else // Otherwise use regular data buffer
|
||||||
sample = baseband.data[offset];
|
sample = baseband.data[offset];
|
||||||
// DC offset removal
|
// DC offset removal
|
||||||
int16_t s = sample - (int16_t) getQuantizationEma();
|
int16_t s = sample - static_cast< int16_t >(qnt_ema);
|
||||||
if (s > getQuantizationMax() / 2)
|
if (s > static_cast< int16_t >(qnt_max) / 2)
|
||||||
return +3;
|
return +3;
|
||||||
else if (s < getQuantizationMin() / 2)
|
else if (s < static_cast< int16_t >(qnt_min) / 2)
|
||||||
return -3;
|
return -3;
|
||||||
else if (s > 0)
|
else if (s > 0)
|
||||||
return +1;
|
return +1;
|
||||||
|
|
@ -287,8 +268,10 @@ bool M17Demodulator::update()
|
||||||
M17::sync_t syncword = { 0, false };
|
M17::sync_t syncword = { 0, false };
|
||||||
int32_t offset = locked ? 0 : -(int32_t) M17_BRIDGE_SIZE;
|
int32_t offset = locked ? 0 : -(int32_t) M17_BRIDGE_SIZE;
|
||||||
uint16_t decoded_syms = 0;
|
uint16_t decoded_syms = 0;
|
||||||
|
|
||||||
// Read samples from the ADC
|
// Read samples from the ADC
|
||||||
baseband = inputStream_getData(basebandId);
|
baseband = inputStream_getData(basebandId);
|
||||||
|
|
||||||
#ifdef PLATFORM_LINUX
|
#ifdef PLATFORM_LINUX
|
||||||
FILE *csv_log = fopen("demod_log_2.csv", "a");
|
FILE *csv_log = fopen("demod_log_2.csv", "a");
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -301,16 +284,12 @@ bool M17Demodulator::update()
|
||||||
{
|
{
|
||||||
float elem = static_cast< float >(baseband.data[i]);
|
float elem = static_cast< float >(baseband.data[i]);
|
||||||
baseband.data[i] = static_cast< int16_t >(M17::rrc(elem));
|
baseband.data[i] = static_cast< int16_t >(M17::rrc(elem));
|
||||||
//samples_fifo.push_back(baseband.data[i]);
|
|
||||||
//if (samples_fifo.size() > SCREEN_WIDTH)
|
|
||||||
// samples_fifo.pop_front();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the buffer
|
// Process the buffer
|
||||||
while(syncword.index != -1 &&
|
int32_t symbol_index = 0;
|
||||||
(offset + phase +
|
while((syncword.index != -1) &&
|
||||||
(int32_t) M17_SAMPLES_PER_SYMBOL * decoded_syms <
|
(symbol_index < static_cast< int32_t > (baseband.len)))
|
||||||
(int32_t) baseband.len))
|
|
||||||
{
|
{
|
||||||
// If we are not locked search for a syncword
|
// If we are not locked search for a syncword
|
||||||
if (!locked)
|
if (!locked)
|
||||||
|
|
@ -319,7 +298,7 @@ bool M17Demodulator::update()
|
||||||
if (syncword.index != -1) // Lock was just acquired
|
if (syncword.index != -1) // Lock was just acquired
|
||||||
{
|
{
|
||||||
locked = true;
|
locked = true;
|
||||||
isLSF = syncword.lsf;
|
isLSF = syncword.lsf;
|
||||||
offset = syncword.index + 1;
|
offset = syncword.index + 1;
|
||||||
frameIndex = 0;
|
frameIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -328,9 +307,13 @@ bool M17Demodulator::update()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Slice the input buffer to extract a frame and quantize
|
// Slice the input buffer to extract a frame and quantize
|
||||||
int32_t symbol_index = offset + phase + M17_SAMPLES_PER_SYMBOL * decoded_syms;
|
symbol_index = offset
|
||||||
|
+ phase
|
||||||
|
+ (M17_SAMPLES_PER_SYMBOL * decoded_syms);
|
||||||
|
|
||||||
updateQuantizationStats(symbol_index);
|
updateQuantizationStats(symbol_index);
|
||||||
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 ",%f,%f,%d,%d\n",
|
||||||
baseband.data[symbol_index] - (int16_t) qnt_ema,
|
baseband.data[symbol_index] - (int16_t) qnt_ema,
|
||||||
|
|
@ -339,6 +322,7 @@ bool M17Demodulator::update()
|
||||||
symbol * 666,
|
symbol * 666,
|
||||||
frameIndex == 0 ? 2300 : symbol_index);
|
frameIndex == 0 ? 2300 : symbol_index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setSymbol<M17_FRAME_BYTES>(*activeFrame, frameIndex, symbol);
|
setSymbol<M17_FRAME_BYTES>(*activeFrame, frameIndex, symbol);
|
||||||
decoded_syms++;
|
decoded_syms++;
|
||||||
frameIndex++;
|
frameIndex++;
|
||||||
|
|
@ -349,27 +333,27 @@ bool M17Demodulator::update()
|
||||||
std::swap(activeFrame, idleFrame);
|
std::swap(activeFrame, idleFrame);
|
||||||
frameIndex = 0;
|
frameIndex = 0;
|
||||||
newFrame = true;
|
newFrame = true;
|
||||||
|
|
||||||
// DEBUG: print idleFrame bytes
|
|
||||||
for(size_t i = 0; i < idleFrame->size(); i+=2)
|
|
||||||
{
|
|
||||||
if (i % 16 == 14)
|
|
||||||
printf("\r\n");
|
|
||||||
printf(" %02X%02X", (*idleFrame)[i], (*idleFrame)[i+1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If syncword is not valid, lock is lost, accept 2 bit errors
|
// If syncword is not valid, lock is lost, accept 2 bit errors
|
||||||
|
uint8_t hammingSync = hammingDistance((*activeFrame)[0],
|
||||||
|
stream_syncword_bytes[0])
|
||||||
|
+ hammingDistance((*activeFrame)[1],
|
||||||
|
stream_syncword_bytes[1]);
|
||||||
|
|
||||||
|
uint8_t hammingLsf = hammingDistance((*activeFrame)[0],
|
||||||
|
lsf_syncword_bytes[0])
|
||||||
|
+ hammingDistance((*activeFrame)[1],
|
||||||
|
lsf_syncword_bytes[1]);
|
||||||
|
|
||||||
if ((frameIndex == M17_SYNCWORD_SYMBOLS) &&
|
if ((frameIndex == M17_SYNCWORD_SYMBOLS) &&
|
||||||
(hammingDistance((*activeFrame)[0], stream_syncword_bytes[0]) +
|
(hammingSync > 2) && (hammingLsf > 2))
|
||||||
hammingDistance((*activeFrame)[1], stream_syncword_bytes[1]) > 2) &&
|
|
||||||
(hammingDistance((*activeFrame)[0], lsf_syncword_bytes[0]) +
|
|
||||||
hammingDistance((*activeFrame)[1], lsf_syncword_bytes[1]) > 2))
|
|
||||||
{
|
{
|
||||||
locked = false;
|
locked = false;
|
||||||
std::swap(activeFrame, idleFrame);
|
std::swap(activeFrame, idleFrame);
|
||||||
frameIndex = 0;
|
frameIndex = 0;
|
||||||
newFrame = true;
|
newFrame = true;
|
||||||
|
|
||||||
#ifdef PLATFORM_MOD17
|
#ifdef PLATFORM_MOD17
|
||||||
gpio_clearPin(SYNC_LED);
|
gpio_clearPin(SYNC_LED);
|
||||||
#endif // PLATFORM_MOD17
|
#endif // PLATFORM_MOD17
|
||||||
|
|
@ -398,12 +382,10 @@ bool M17Demodulator::update()
|
||||||
sizeof(int16_t) * M17_BRIDGE_SIZE);
|
sizeof(int16_t) * M17_BRIDGE_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//gfx_plotData({0, 0}, SCREEN_WIDTH, SCREEN_HEIGHT, samples_fifo);
|
|
||||||
#ifdef PLATFORM_LINUX
|
#ifdef PLATFORM_LINUX
|
||||||
fclose(csv_log);
|
fclose(csv_log);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return newFrame;
|
return newFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* M17 */
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue