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

This commit is contained in:
Silvano Seva 2022-02-16 14:21:00 +01:00
parent 3372da2b64
commit 427c5f50b3
2 changed files with 68 additions and 47 deletions

View File

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

View File

@ -1,9 +1,11 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, * * Copyright (C) 2021 - 2022 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN * * Niccolò Izzo IU2KIN *
* Wojciech Kaczmarski SP5WWP *
* Frederik Saraci IU2NRO * * Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO * * Silvano Seva IU2KWO *
* * * *
* *
* This program is free software; you can redistribute it and/or modify * * 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 * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or * * the Free Software Foundation; either version 3 of the License, or *
@ -56,12 +58,13 @@ void M17Demodulator::init()
baseband_buffer = new int16_t[2 * M17_INPUT_BUF_SIZE]; baseband_buffer = new int16_t[2 * M17_INPUT_BUF_SIZE];
baseband = { nullptr, 0 }; baseband = { nullptr, 0 };
activeFrame = new dataFrame_t; activeFrame = new frame_t;
rawFrame = new uint16_t[M17_FRAME_SYMBOLS]; rawFrame = new uint16_t[M17_FRAME_SYMBOLS];
idleFrame = new dataFrame_t; idleFrame = new frame_t;
frameIndex = 0; frameIndex = 0;
phase = 0; phase = 0;
locked = false; locked = false;
newFrame = false;
#ifdef PLATFORM_LINUX #ifdef PLATFORM_LINUX
FILE *csv_log = fopen("demod_log_1.csv", "w"); FILE *csv_log = fopen("demod_log_1.csv", "w");
@ -262,8 +265,10 @@ int8_t M17Demodulator::quantize(int32_t offset)
return -1; 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; return *activeFrame;
} }
@ -277,7 +282,7 @@ uint8_t M17Demodulator::hammingDistance(uint8_t x, uint8_t y)
return __builtin_popcount(x ^ y); return __builtin_popcount(x ^ y);
} }
void M17Demodulator::update() 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;
@ -300,6 +305,7 @@ void M17Demodulator::update()
//if (samples_fifo.size() > SCREEN_WIDTH) //if (samples_fifo.size() > SCREEN_WIDTH)
// samples_fifo.pop_front(); // samples_fifo.pop_front();
} }
// Process the buffer // Process the buffer
while(syncword.index != -1 && while(syncword.index != -1 &&
(offset + phase + (offset + phase +
@ -336,11 +342,14 @@ void M17Demodulator::update()
setSymbol<M17_FRAME_BYTES>(*activeFrame, frameIndex, symbol); setSymbol<M17_FRAME_BYTES>(*activeFrame, frameIndex, symbol);
decoded_syms++; decoded_syms++;
frameIndex++; frameIndex++;
// If the frame buffer is full switch active and idle frame // If the frame buffer is full switch active and idle frame
if (frameIndex == M17_FRAME_SYMBOLS) if (frameIndex == M17_FRAME_SYMBOLS)
{ {
std::swap(activeFrame, idleFrame); std::swap(activeFrame, idleFrame);
frameIndex = 0; frameIndex = 0;
newFrame = true;
// DEBUG: print idleFrame bytes // DEBUG: print idleFrame bytes
for(size_t i = 0; i < idleFrame->size(); i+=2) 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]); 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
if (frameIndex == M17_SYNCWORD_SYMBOLS && if ((frameIndex == M17_SYNCWORD_SYMBOLS) &&
(hammingDistance((*activeFrame)[0], stream_syncword_bytes[0]) + (hammingDistance((*activeFrame)[0], stream_syncword_bytes[0]) +
hammingDistance((*activeFrame)[1], stream_syncword_bytes[1]) > 2) && hammingDistance((*activeFrame)[1], stream_syncword_bytes[1]) > 2) &&
(hammingDistance((*activeFrame)[0], lsf_syncword_bytes[0]) + (hammingDistance((*activeFrame)[0], lsf_syncword_bytes[0]) +
@ -359,10 +369,12 @@ void M17Demodulator::update()
locked = false; locked = false;
std::swap(activeFrame, idleFrame); std::swap(activeFrame, idleFrame);
frameIndex = 0; frameIndex = 0;
newFrame = true;
#ifdef PLATFORM_MOD17 #ifdef PLATFORM_MOD17
gpio_clearPin(SYNC_LED); gpio_clearPin(SYNC_LED);
#endif // PLATFORM_MOD17 #endif // PLATFORM_MOD17
} else if (frameIndex == M17_SYNCWORD_SYMBOLS) }
else if (frameIndex == M17_SYNCWORD_SYMBOLS)
{ {
#ifdef PLATFORM_MOD17 #ifdef PLATFORM_MOD17
gpio_setPin(SYNC_LED); gpio_setPin(SYNC_LED);
@ -370,11 +382,12 @@ void M17Demodulator::update()
} }
} }
} }
// We are at the end of the buffer // We are at the end of the buffer
if (locked) if (locked)
{ {
// Compute phase of next buffer // 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); (M17_INPUT_BUF_SIZE % M17_SAMPLES_PER_SYMBOL);
} }
else else
@ -389,6 +402,8 @@ void M17Demodulator::update()
#ifdef PLATFORM_LINUX #ifdef PLATFORM_LINUX
fclose(csv_log); fclose(csv_log);
#endif #endif
return newFrame;
} }
} /* M17 */ } /* M17 */