Improved robustness of frame type detection, now based on minimum hamming distance between syncwords
This commit is contained in:
parent
115982d279
commit
7aff678069
|
|
@ -238,14 +238,6 @@ private:
|
||||||
*/
|
*/
|
||||||
int8_t quantize(int32_t offset);
|
int8_t quantize(int32_t offset);
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute Hamming Distance between two bytes
|
|
||||||
*
|
|
||||||
* @param x: first byte
|
|
||||||
* @param y: second byte
|
|
||||||
*/
|
|
||||||
uint8_t hammingDistance(uint8_t x, uint8_t y);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a limited search for a syncword using correlation
|
* Perform a limited search for a syncword using correlation
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#error This header is C++ only!
|
#error This header is C++ only!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include "M17LinkSetupFrame.h"
|
#include "M17LinkSetupFrame.h"
|
||||||
|
|
@ -97,6 +98,17 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine frame type by searching which syncword among the standard M17
|
||||||
|
* ones has the minumum hamming distance from the given one. If the hamming
|
||||||
|
* distance exceeds a masimum absolute threshold the frame is declared of
|
||||||
|
* unknown type.
|
||||||
|
*
|
||||||
|
* @param syncWord: frame syncword.
|
||||||
|
* @return frame type based on the given syncword.
|
||||||
|
*/
|
||||||
|
M17FrameType getFrameType(const std::array< uint8_t, 2 >& syncWord);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode Link Setup Frame data and update the internal LSF field with
|
* Decode Link Setup Frame data and update the internal LSF field with
|
||||||
* the new frame data.
|
* the new frame data.
|
||||||
|
|
@ -129,6 +141,9 @@ private:
|
||||||
M17LinkSetupFrame lsfFromLich; ///< LSF assembled from LICH segments.
|
M17LinkSetupFrame lsfFromLich; ///< LSF assembled from LICH segments.
|
||||||
M17StreamFrame streamFrame; ///< Latest stream dat frame received.
|
M17StreamFrame streamFrame; ///< Latest stream dat frame received.
|
||||||
M17Viterbi viterbi; ///< Viterbi decoder.
|
M17Viterbi viterbi; ///< Viterbi decoder.
|
||||||
|
|
||||||
|
///< Maximum allowed hamming distance when determining the frame type.
|
||||||
|
static constexpr uint8_t MAX_SYNC_HAMM_DISTANCE = 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace M17
|
} // namespace M17
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,9 @@ namespace M17
|
||||||
* of bytes. Bits are counted scanning from left to right, thus bit number zero
|
* of bytes. Bits are counted scanning from left to right, thus bit number zero
|
||||||
* is the leftmost bit of array[0].
|
* is the leftmost bit of array[0].
|
||||||
*
|
*
|
||||||
* \param array: byte array.
|
* @param array: byte array.
|
||||||
* \param pos: bit position inside the array.
|
* @param pos: bit position inside the array.
|
||||||
* \return value of the indexed bit, as boolean variable.
|
* @return value of the indexed bit, as boolean variable.
|
||||||
*/
|
*/
|
||||||
template < size_t N >
|
template < size_t N >
|
||||||
inline bool getBit(const std::array< uint8_t, N >& array, const size_t pos)
|
inline bool getBit(const std::array< uint8_t, N >& array, const size_t pos)
|
||||||
|
|
@ -57,9 +57,9 @@ inline bool getBit(const std::array< uint8_t, N >& array, const size_t pos)
|
||||||
* of bytes. Bits are counted scanning from left to right, thus bit number zero
|
* of bytes. Bits are counted scanning from left to right, thus bit number zero
|
||||||
* is the leftmost bit of array[0].
|
* is the leftmost bit of array[0].
|
||||||
*
|
*
|
||||||
* \param array: byte array.
|
* @param array: byte array.
|
||||||
* \param pos: bit position inside the array.
|
* @param pos: bit position inside the array.
|
||||||
* \param bit: bit value to be set.
|
* @param bit: bit value to be set.
|
||||||
*/
|
*/
|
||||||
template < size_t N >
|
template < size_t N >
|
||||||
inline void setBit(std::array< uint8_t, N >& array, const size_t pos,
|
inline void setBit(std::array< uint8_t, N >& array, const size_t pos,
|
||||||
|
|
@ -78,9 +78,9 @@ inline void setBit(std::array< uint8_t, N >& array, const size_t pos,
|
||||||
* symbols are filled from the least significant bit pair to the most
|
* symbols are filled from the least significant bit pair to the most
|
||||||
* significant bit pair.
|
* significant bit pair.
|
||||||
*
|
*
|
||||||
* \param array: byte array.
|
* @param array: byte array.
|
||||||
* \param pos: symbol position inside the array.
|
* @param pos: symbol position inside the array.
|
||||||
* \param symbol: symbol to be set, either -3, -1, +1, +3.
|
* @param symbol: symbol to be set, either -3, -1, +1, +3.
|
||||||
*/
|
*/
|
||||||
template < size_t N >
|
template < size_t N >
|
||||||
inline void setSymbol(std::array< uint8_t, N >& array, const size_t pos,
|
inline void setSymbol(std::array< uint8_t, N >& array, const size_t pos,
|
||||||
|
|
@ -108,6 +108,18 @@ inline void setSymbol(std::array< uint8_t, N >& array, const size_t pos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the hamming distance between two bytes.
|
||||||
|
*
|
||||||
|
* @param x: first byte.
|
||||||
|
* @param y: second byte.
|
||||||
|
* @return hamming distance between x and y.
|
||||||
|
*/
|
||||||
|
static inline uint8_t hammingDistance(const uint8_t x, const uint8_t y)
|
||||||
|
{
|
||||||
|
return __builtin_popcount(x ^ y);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace M17
|
} // namespace M17
|
||||||
|
|
||||||
#endif // M17_UTILS_H
|
#endif // M17_UTILS_H
|
||||||
|
|
|
||||||
|
|
@ -310,11 +310,6 @@ bool M17::M17Demodulator::isLocked()
|
||||||
return locked;
|
return locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t M17Demodulator::hammingDistance(uint8_t x, uint8_t y)
|
|
||||||
{
|
|
||||||
return __builtin_popcount(x ^ y);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t M17Demodulator::syncwordSweep(int32_t offset)
|
int32_t M17Demodulator::syncwordSweep(int32_t offset)
|
||||||
{
|
{
|
||||||
int32_t max_conv = 0, max_index = 0;
|
int32_t max_conv = 0, max_index = 0;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <M17/M17Interleaver.h>
|
#include <M17/M17Interleaver.h>
|
||||||
#include <M17/M17Decorrelator.h>
|
#include <M17/M17Decorrelator.h>
|
||||||
#include <M17/M17CodePuncturing.h>
|
#include <M17/M17CodePuncturing.h>
|
||||||
|
#include <M17/M17Utils.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace M17;
|
using namespace M17;
|
||||||
|
|
@ -51,30 +52,58 @@ M17FrameType M17FrameDecoder::decodeFrame(const frame_t& frame)
|
||||||
decorrelate(data);
|
decorrelate(data);
|
||||||
deinterleave(data);
|
deinterleave(data);
|
||||||
|
|
||||||
|
auto type = getFrameType(syncWord);
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case M17FrameType::LINK_SETUP:
|
||||||
|
decodeLSF(data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case M17FrameType::STREAM:
|
||||||
|
decodeStream(data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
M17FrameType M17FrameDecoder::getFrameType(const std::array< uint8_t, 2 >& syncWord)
|
||||||
|
{
|
||||||
// Preamble
|
// Preamble
|
||||||
if((syncWord[0] == 0x77) && (syncWord[1] == 0x77))
|
M17FrameType type = M17FrameType::PREAMBLE;
|
||||||
|
uint8_t minDistance = hammingDistance(syncWord[0], 0x77)
|
||||||
|
+ hammingDistance(syncWord[1], 0x77);
|
||||||
|
|
||||||
|
// Link setup frame
|
||||||
|
uint8_t hammDistance = hammingDistance(syncWord[0], LSF_SYNC_WORD[0])
|
||||||
|
+ hammingDistance(syncWord[1], LSF_SYNC_WORD[1]);
|
||||||
|
if(hammDistance < minDistance)
|
||||||
{
|
{
|
||||||
return M17FrameType::PREAMBLE;
|
type = M17FrameType::LINK_SETUP;
|
||||||
|
minDistance = hammDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link Setup Frame
|
// Stream frame
|
||||||
if(syncWord == LSF_SYNC_WORD)
|
hammDistance = hammingDistance(syncWord[0], STREAM_SYNC_WORD[0])
|
||||||
|
+ hammingDistance(syncWord[1], STREAM_SYNC_WORD[1]);
|
||||||
|
if(hammDistance < minDistance)
|
||||||
{
|
{
|
||||||
decodeLSF(data);
|
type = M17FrameType::STREAM;
|
||||||
return M17FrameType::LINK_SETUP;
|
minDistance = hammDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stream data frame
|
// Check value of minimum hamming distance found, if exceeds the allowed
|
||||||
uint8_t hd = __builtin_popcount(syncWord[0] ^ STREAM_SYNC_WORD[0])
|
// limit consider the frame as of unknown type.
|
||||||
+ __builtin_popcount(syncWord[1] ^ STREAM_SYNC_WORD[1]);
|
if(minDistance > MAX_SYNC_HAMM_DISTANCE)
|
||||||
if(hd <= 4)
|
|
||||||
{
|
{
|
||||||
decodeStream(data);
|
type = M17FrameType::UNKNOWN;
|
||||||
return M17FrameType::STREAM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, we received an unknown frame
|
return type;
|
||||||
return M17FrameType::UNKNOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void M17FrameDecoder::decodeLSF(const std::array< uint8_t, 46 >& data)
|
void M17FrameDecoder::decodeLSF(const std::array< uint8_t, 46 >& data)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue