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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#error This header is C++ only!
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include "M17LinkSetupFrame.h"
|
||||
|
|
@ -97,6 +98,17 @@ public:
|
|||
|
||||
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
|
||||
* the new frame data.
|
||||
|
|
@ -129,6 +141,9 @@ private:
|
|||
M17LinkSetupFrame lsfFromLich; ///< LSF assembled from LICH segments.
|
||||
M17StreamFrame streamFrame; ///< Latest stream dat frame received.
|
||||
M17Viterbi viterbi; ///< Viterbi decoder.
|
||||
|
||||
///< Maximum allowed hamming distance when determining the frame type.
|
||||
static constexpr uint8_t MAX_SYNC_HAMM_DISTANCE = 4;
|
||||
};
|
||||
|
||||
} // namespace M17
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@ namespace M17
|
|||
* of bytes. Bits are counted scanning from left to right, thus bit number zero
|
||||
* is the leftmost bit of array[0].
|
||||
*
|
||||
* \param array: byte array.
|
||||
* \param pos: bit position inside the array.
|
||||
* \return value of the indexed bit, as boolean variable.
|
||||
* @param array: byte array.
|
||||
* @param pos: bit position inside the array.
|
||||
* @return value of the indexed bit, as boolean variable.
|
||||
*/
|
||||
template < size_t N >
|
||||
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
|
||||
* is the leftmost bit of array[0].
|
||||
*
|
||||
* \param array: byte array.
|
||||
* \param pos: bit position inside the array.
|
||||
* \param bit: bit value to be set.
|
||||
* @param array: byte array.
|
||||
* @param pos: bit position inside the array.
|
||||
* @param bit: bit value to be set.
|
||||
*/
|
||||
template < size_t N >
|
||||
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
|
||||
* significant bit pair.
|
||||
*
|
||||
* \param array: byte array.
|
||||
* \param pos: symbol position inside the array.
|
||||
* \param symbol: symbol to be set, either -3, -1, +1, +3.
|
||||
* @param array: byte array.
|
||||
* @param pos: symbol position inside the array.
|
||||
* @param symbol: symbol to be set, either -3, -1, +1, +3.
|
||||
*/
|
||||
template < size_t N >
|
||||
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
|
||||
|
||||
#endif // M17_UTILS_H
|
||||
|
|
|
|||
|
|
@ -310,11 +310,6 @@ bool M17::M17Demodulator::isLocked()
|
|||
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 max_conv = 0, max_index = 0;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <M17/M17Interleaver.h>
|
||||
#include <M17/M17Decorrelator.h>
|
||||
#include <M17/M17CodePuncturing.h>
|
||||
#include <M17/M17Utils.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace M17;
|
||||
|
|
@ -51,30 +52,58 @@ M17FrameType M17FrameDecoder::decodeFrame(const frame_t& frame)
|
|||
decorrelate(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
|
||||
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
|
||||
if(syncWord == LSF_SYNC_WORD)
|
||||
// Stream frame
|
||||
hammDistance = hammingDistance(syncWord[0], STREAM_SYNC_WORD[0])
|
||||
+ hammingDistance(syncWord[1], STREAM_SYNC_WORD[1]);
|
||||
if(hammDistance < minDistance)
|
||||
{
|
||||
decodeLSF(data);
|
||||
return M17FrameType::LINK_SETUP;
|
||||
type = M17FrameType::STREAM;
|
||||
minDistance = hammDistance;
|
||||
}
|
||||
|
||||
// Stream data frame
|
||||
uint8_t hd = __builtin_popcount(syncWord[0] ^ STREAM_SYNC_WORD[0])
|
||||
+ __builtin_popcount(syncWord[1] ^ STREAM_SYNC_WORD[1]);
|
||||
if(hd <= 4)
|
||||
// Check value of minimum hamming distance found, if exceeds the allowed
|
||||
// limit consider the frame as of unknown type.
|
||||
if(minDistance > MAX_SYNC_HAMM_DISTANCE)
|
||||
{
|
||||
decodeStream(data);
|
||||
return M17FrameType::STREAM;
|
||||
type = M17FrameType::UNKNOWN;
|
||||
}
|
||||
|
||||
// If we get here, we received an unknown frame
|
||||
return M17FrameType::UNKNOWN;
|
||||
return type;
|
||||
}
|
||||
|
||||
void M17FrameDecoder::decodeLSF(const std::array< uint8_t, 46 >& data)
|
||||
|
|
|
|||
Loading…
Reference in New Issue