Made M17Demodulator::update() return a boolean indicating when a new decoded frame is ready

pull/68/head
Silvano Seva 2022-02-16 14:21:00 +01:00
rodzic 3372da2b64
commit 427c5f50b3
2 zmienionych plików z 68 dodań i 47 usunięć

Wyświetl plik

@ -1,9 +1,9 @@
/***************************************************************************
* Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Wojciech Kaczmarski SP5WWP *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* Copyright (C) 2021 - 2022 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Wojciech Kaczmarski SP5WWP *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* *
* This program is free software; you can redistribute it and/or modify *
@ -33,6 +33,7 @@
#include <interfaces/audio_stream.h>
#include <hwconfig.h>
#include <deque>
#include "M17Datatypes.h"
namespace M17
{
@ -47,11 +48,6 @@ class M17Demodulator
{
public:
/**
* Deque containing the sliced samples
*/
std::deque<int16_t> samples_fifo;
/**
* Constructor.
*/
@ -84,19 +80,24 @@ public:
/**
* Returns the a frame decoded from the baseband signal.
*
* @return reference to the internal data structure containing the last
* decoded frame.
*/
const std::array<uint8_t, 48> &getFrame();
const frame_t& getFrame();
/**
* Returns a flag indicating whether the decoded frame is an LSF.
* @return true if the last decoded frame is an LSF.
*/
bool isFrameLSF();
/**
* Demodulates data from the ADC and fills the idle frame
* Everytime this function is called a whole ADC buffer is consumed
* Demodulates data from the ADC and fills the idle frame.
* Everytime this function is called a whole ADC buffer is consumed.
*
* @return true if a new frame has been fully decoded.
*/
void update();
bool update();
private:
@ -127,7 +128,6 @@ private:
uint8_t stream_syncword_bytes[2] = {0xff, 0x5d};
using dataBuffer_t = std::array< int16_t, M17_FRAME_SAMPLES_24K >;
using dataFrame_t = std::array< uint8_t, M17_FRAME_BYTES >;
/*
* Buffers
@ -137,10 +137,11 @@ private:
dataBlock_t baseband; ///< Half buffer, free to be processed.
uint16_t *rawFrame; ///< Analog values to be quantized.
uint16_t frameIndex; ///< Index for filling the raw frame.
dataFrame_t *activeFrame; ///< Half frame, in demodulation.
dataFrame_t *idleFrame; ///< Half frame, free to be processed.
frame_t *activeFrame; ///< Half frame, in demodulation.
frame_t *idleFrame; ///< Half frame, free to be processed.
bool isLSF; ///< Indicates that we demodualated an LSF.
bool locked; ///< A syncword was detected.
bool newFrame; ///< A new frame has been fully decoded.
int16_t basebandBridge[M17_BRIDGE_SIZE] = { 0 }; ///< Bridge buffer
uint16_t phase; ///< Phase of the signal w.r.t. sampling
@ -162,6 +163,11 @@ private:
float qnt_max = 0.0f;
float qnt_min = 0.0f;
/**
* Deque containing the sliced samples
*/
// std::deque<int16_t> samples_fifo;
/**
* Resets the exponential mean and variance/stddev computation.
*/

Wyświetl plik

@ -1,8 +1,10 @@
/***************************************************************************
* Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* Copyright (C) 2021 - 2022 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Wojciech Kaczmarski SP5WWP *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@ -56,21 +58,22 @@ void M17Demodulator::init()
baseband_buffer = new int16_t[2 * M17_INPUT_BUF_SIZE];
baseband = { nullptr, 0 };
activeFrame = new dataFrame_t;
activeFrame = new frame_t;
rawFrame = new uint16_t[M17_FRAME_SYMBOLS];
idleFrame = new dataFrame_t;
idleFrame = new frame_t;
frameIndex = 0;
phase = 0;
locked = false;
newFrame = false;
#ifdef PLATFORM_LINUX
#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");
fclose(csv_log);
#endif // PLATFORM_MOD17
#endif // PLATFORM_MOD17
}
void M17Demodulator::terminate()
@ -193,9 +196,9 @@ int32_t M17Demodulator::convolution(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");
#endif
#endif
sync_t syncword = { -1, false };
// Find peaks in the correlation between the baseband and the frame syncword
// Leverage the fact LSF syncword is the opposite of the frame syncword
@ -215,13 +218,13 @@ sync_t M17Demodulator::nextFrameSync(int32_t offset)
sample = basebandBridge[M17_BRIDGE_SIZE + i];
else // Otherwise use regular data buffer
sample = baseband.data[i];
#ifdef PLATFORM_LINUX
#ifdef PLATFORM_LINUX
fprintf(csv_log, "%" PRId16 ",%d,%f,%d\n",
sample,
conv - (int32_t) getCorrelationEma(),
conv_threshold_factor * getCorrelationStddev(),
i);
#endif
#endif
// Positive correlation peak -> frame syncword
if (conv - (int32_t) getCorrelationEma() >
getCorrelationStddev() * conv_threshold_factor)
@ -237,9 +240,9 @@ sync_t M17Demodulator::nextFrameSync(int32_t offset)
syncword.index = i;
}
}
#ifdef PLATFORM_LINUX
#ifdef PLATFORM_LINUX
fclose(csv_log);
#endif
#endif
return syncword;
}
@ -262,8 +265,10 @@ int8_t M17Demodulator::quantize(int32_t offset)
return -1;
}
const std::array<uint8_t, 48> &M17Demodulator::getFrame()
const frame_t& M17Demodulator::getFrame()
{
// When a frame is read is not new anymore
newFrame = false;
return *activeFrame;
}
@ -277,16 +282,16 @@ uint8_t M17Demodulator::hammingDistance(uint8_t x, uint8_t y)
return __builtin_popcount(x ^ y);
}
void M17Demodulator::update()
bool M17Demodulator::update()
{
M17::sync_t syncword = { 0, false };
int32_t offset = locked ? 0 : -(int32_t) M17_BRIDGE_SIZE;
uint16_t decoded_syms = 0;
// Read samples from the ADC
baseband = inputStream_getData(basebandId);
#ifdef PLATFORM_LINUX
#ifdef PLATFORM_LINUX
FILE *csv_log = fopen("demod_log_2.csv", "a");
#endif
#endif
if(baseband.data != NULL)
@ -300,6 +305,7 @@ void M17Demodulator::update()
//if (samples_fifo.size() > SCREEN_WIDTH)
// samples_fifo.pop_front();
}
// Process the buffer
while(syncword.index != -1 &&
(offset + phase +
@ -325,22 +331,25 @@ void M17Demodulator::update()
int32_t symbol_index = offset + phase + M17_SAMPLES_PER_SYMBOL * decoded_syms;
updateQuantizationStats(symbol_index);
int8_t symbol = quantize(symbol_index);
#ifdef PLATFORM_LINUX
#ifdef PLATFORM_LINUX
fprintf(csv_log, "%" PRId16 ",%f,%f,%d,%d\n",
baseband.data[symbol_index] - (int16_t) qnt_ema,
getQuantizationMax() / 2,
getQuantizationMin() / 2,
symbol * 666,
frameIndex == 0 ? 2300 : symbol_index);
#endif
#endif
setSymbol<M17_FRAME_BYTES>(*activeFrame, frameIndex, symbol);
decoded_syms++;
frameIndex++;
// If the frame buffer is full switch active and idle frame
if (frameIndex == M17_FRAME_SYMBOLS)
{
std::swap(activeFrame, idleFrame);
frameIndex = 0;
newFrame = true;
// DEBUG: print idleFrame bytes
for(size_t i = 0; i < idleFrame->size(); i+=2)
{
@ -349,8 +358,9 @@ void M17Demodulator::update()
printf(" %02X%02X", (*idleFrame)[i], (*idleFrame)[i+1]);
}
}
// If syncword is not valid, lock is lost, accept 2 bit errors
if (frameIndex == M17_SYNCWORD_SYMBOLS &&
if ((frameIndex == M17_SYNCWORD_SYMBOLS) &&
(hammingDistance((*activeFrame)[0], stream_syncword_bytes[0]) +
hammingDistance((*activeFrame)[1], stream_syncword_bytes[1]) > 2) &&
(hammingDistance((*activeFrame)[0], lsf_syncword_bytes[0]) +
@ -359,22 +369,25 @@ void M17Demodulator::update()
locked = false;
std::swap(activeFrame, idleFrame);
frameIndex = 0;
#ifdef PLATFORM_MOD17
newFrame = true;
#ifdef PLATFORM_MOD17
gpio_clearPin(SYNC_LED);
#endif // PLATFORM_MOD17
} else if (frameIndex == M17_SYNCWORD_SYMBOLS)
#endif // PLATFORM_MOD17
}
else if (frameIndex == M17_SYNCWORD_SYMBOLS)
{
#ifdef PLATFORM_MOD17
#ifdef PLATFORM_MOD17
gpio_setPin(SYNC_LED);
#endif // PLATFORM_MOD17
#endif // PLATFORM_MOD17
}
}
}
// We are at the end of the buffer
if (locked)
{
// Compute phase of next buffer
phase = offset % M17_SAMPLES_PER_SYMBOL +
phase = (offset % M17_SAMPLES_PER_SYMBOL) +
(M17_INPUT_BUF_SIZE % M17_SAMPLES_PER_SYMBOL);
}
else
@ -386,9 +399,11 @@ void M17Demodulator::update()
}
}
//gfx_plotData({0, 0}, SCREEN_WIDTH, SCREEN_HEIGHT, samples_fifo);
#ifdef PLATFORM_LINUX
#ifdef PLATFORM_LINUX
fclose(csv_log);
#endif
#endif
return newFrame;
}
} /* M17 */