mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
* manchester * Added manchester code and test * manchester * Formatting and added missing file * manchester * Some functions can only be constexpr since C++14 * manchester * Manchester decode and some refactoring * manchester * Added some missing typenames * manchester * constexpr void function not allowed in C++11 * manchester * condition on static_assert tests * manchester * revert CMakeLists.txt * Using ETL_STATIC_ASSERT * Some cleanup * manchester * Added static_assert message * manchester * Added compile time tests * manchester * Added invert manchester * Some refactoring * manchester * Disable test for now * Move ETL_NODISCARD before static * manchester * Test for valid_span * manchester * Remove redundant (?) storage specifiers for template specializations. Storage specifier already given in base template * manchester * refactoring to get rid of specialized template functions in template class * manchester * cleanup * manchester * Added documentation comments * Some refactoring * manchester * introducing namespace detail_manchester * manchester * Some refactoring * Update tests * manchester * Some refactoring * Removed possible undefined behavior by refactoring encode_span * constexpr version of encode_span * Static assertion for rare case where code doesn't work because CHAR_BIT is not the same as the number of bits in uint_least8_t * manchester * renamed valid to is_valid * manchester * renamed is_valid_span to is_valid * Using etl exceptions in ETL_ASSERT * manchester * Removed _fast functions * merged encode_in_place with encode and decode_in_place with decode * removed _span to create normal overloads of encode and decode for span * Some renaming and minor refactoring * manchester * Fix build issues * manchester * Conditionally compile manchester_decoded * Update test_manchester.cpp Removed redundant semicolon * #1258 Manchester coding * Formatting * consistency: hex literals with lower case 0x * #1258 Manchester coding * Moved copyright to top of file * Make constexpr encode/decode span functions equal for little and big endian platforms * #1258 Manchester coding * Added missing include * Added missing 8bit/64bit guards * Fixed is_valid for big endian platforms * #1258 Manchester coding * private memcpy alias * #1258 Manchester coding * Review comments * #1258 Manchester coding * Cleanup * Fix build error --------- Co-authored-by: Timon Zijnge <timon.zijnge@imec.nl>
This commit is contained in:
parent
7ef01fcaed
commit
810a106bdf
558
include/etl/manchester.h
Normal file
558
include/etl/manchester.h
Normal file
@ -0,0 +1,558 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2026 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_MANCHESTER_INCLUDED
|
||||
#define ETL_MANCHESTER_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "endianness.h"
|
||||
#include "span.h"
|
||||
#include "static_assert.h"
|
||||
#include <cstring>
|
||||
|
||||
///\defgroup manchester manchester
|
||||
/// Manchester encoding and decoding
|
||||
///\ingroup utilities
|
||||
|
||||
namespace etl
|
||||
{
|
||||
namespace private_manchester
|
||||
{
|
||||
//*************************************************************************
|
||||
/// Type trait to determine if a type is supported as an encode input.
|
||||
///\tparam TChunk The input type to check.
|
||||
//*************************************************************************
|
||||
template <typename TChunk>
|
||||
struct is_encodable
|
||||
{
|
||||
static const bool value =
|
||||
#if ETL_USING_8BIT_TYPES
|
||||
etl::is_same<TChunk, uint8_t>::value ||
|
||||
#endif
|
||||
etl::is_same<TChunk, uint16_t>::value
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
|| etl::is_same<TChunk, uint32_t>::value
|
||||
#endif
|
||||
;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Type trait to determine if a type is supported as a decode input.
|
||||
///\tparam TChunk The input type to check.
|
||||
//*************************************************************************
|
||||
template <typename TChunk>
|
||||
struct is_decodable
|
||||
{
|
||||
static const bool value =
|
||||
#if ETL_USING_8BIT_TYPES
|
||||
etl::is_same<TChunk, uint16_t>::value ||
|
||||
#endif
|
||||
etl::is_same<TChunk, uint32_t>::value
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
|| etl::is_same<TChunk, uint64_t>::value
|
||||
#endif
|
||||
;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Type trait to determine the encoded type for a given decoded type.
|
||||
/// Encoding doubles the bit width: uint8_t->uint16_t, uint16_t->uint32_t, etc.
|
||||
///\tparam T The decoded type.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
struct encoded
|
||||
{
|
||||
ETL_STATIC_ASSERT(sizeof(T) == 0, "Manchester encoding type should be one of [uint8_t, uint16_t, uint32_t]");
|
||||
};
|
||||
|
||||
#if ETL_USING_8BIT_TYPES
|
||||
template <>
|
||||
struct encoded<uint8_t>
|
||||
{
|
||||
typedef uint16_t type;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct encoded<uint16_t>
|
||||
{
|
||||
typedef uint32_t type;
|
||||
};
|
||||
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
template <>
|
||||
struct encoded<uint32_t>
|
||||
{
|
||||
typedef uint64_t type;
|
||||
};
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Type trait to determine the decoded type for a given encoded type.
|
||||
/// Decoding halves the bit width: uint16_t->uint8_t, uint32_t->uint16_t, etc.
|
||||
///\tparam T The encoded type.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
struct decoded
|
||||
{
|
||||
ETL_STATIC_ASSERT(sizeof(T) == 0, "Manchester decoding type should be one of [uint16_t, uint32_t, uint64_t]");
|
||||
};
|
||||
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
template <>
|
||||
struct decoded<uint16_t>
|
||||
{
|
||||
typedef uint8_t type;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct decoded<uint32_t>
|
||||
{
|
||||
typedef uint16_t type;
|
||||
};
|
||||
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
template <>
|
||||
struct decoded<uint64_t>
|
||||
{
|
||||
typedef uint32_t type;
|
||||
};
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Normal Manchester encoding type (no inversion).
|
||||
//*************************************************************************
|
||||
struct manchester_type_normal
|
||||
{
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
static const uint64_t inversion_mask = 0x0000000000000000ULL;
|
||||
#else
|
||||
static const uint32_t inversion_mask = 0x00000000UL;
|
||||
#endif
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Inverted Manchester encoding type.
|
||||
//*************************************************************************
|
||||
struct manchester_type_inverted
|
||||
{
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
static const uint64_t inversion_mask = 0xFFFFFFFFFFFFFFFFULL;
|
||||
#else
|
||||
static const uint32_t inversion_mask = 0xFFFFFFFFUL;
|
||||
#endif
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Alias for memcpy. etl::mem_copy is not suitable for the Manchester
|
||||
/// algorithm because all memory copies are between different types. This
|
||||
/// alias is a way to respect ETL_USING_BUILTIN_MEMCPY while using the
|
||||
/// memcpy function signature
|
||||
//*************************************************************************
|
||||
inline void* memcpy(void* dest, const void* src, std::size_t count) ETL_NOEXCEPT
|
||||
{
|
||||
#if ETL_USING_BUILTIN_MEMCPY
|
||||
return __builtin_memcpy(dest, src, count);
|
||||
#else
|
||||
return ::memcpy(dest, src, count);
|
||||
#endif
|
||||
}
|
||||
} // namespace private_manchester
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for Manchester.
|
||||
//***************************************************************************
|
||||
class manchester_exception : public etl::exception
|
||||
{
|
||||
public:
|
||||
manchester_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
: exception(reason_, file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Invalid size exception for Manchester
|
||||
//***************************************************************************
|
||||
class manchester_invalid_size : public etl::manchester_exception
|
||||
{
|
||||
public:
|
||||
manchester_invalid_size(string_type file_name_, numeric_type line_number_)
|
||||
: etl::manchester_exception("manchester:size", file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup manchester
|
||||
/// Base template class for Manchester encoding and decoding.
|
||||
///\tparam TType The Manchester encoding type (normal or inverted).
|
||||
//***************************************************************************
|
||||
template <typename TManchesterType>
|
||||
struct manchester_base
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_same<TManchesterType, private_manchester::manchester_type_normal>::value ||
|
||||
etl::is_same<TManchesterType, private_manchester::manchester_type_inverted>::value),
|
||||
"TManchesterType must be manchester_type_normal or manchester_type_inverted");
|
||||
|
||||
ETL_STATIC_ASSERT(CHAR_BIT == etl::numeric_limits<uint_least8_t>::digits, "Manchester requires uint_least8_t to have the same number of bits as CHAR (CHAR_BITS)");
|
||||
|
||||
//*************************************************************************
|
||||
// Encoding functions
|
||||
//*************************************************************************
|
||||
|
||||
#if ETL_USING_8BIT_TYPES
|
||||
//*************************************************************************
|
||||
/// Encode a 8-bit unsigned value and return 16-bit result.
|
||||
///\param decoded The value to encode.
|
||||
///\return The Manchester encoded value.
|
||||
//*************************************************************************
|
||||
template <typename TDecoded>
|
||||
static ETL_CONSTEXPR14 typename etl::enable_if<etl::is_same<TDecoded, uint8_t>::value, typename private_manchester::encoded<TDecoded>::type>::type
|
||||
encode(TDecoded decoded)
|
||||
{
|
||||
typedef typename private_manchester::encoded<TDecoded>::type TEncoded;
|
||||
|
||||
TEncoded encoded = decoded;
|
||||
|
||||
encoded = (encoded | (encoded << 4U)) & 0x0F0FU;
|
||||
encoded = (encoded | (encoded << 2U)) & 0x3333U;
|
||||
encoded = (encoded | (encoded << 1U)) & 0x5555U;
|
||||
encoded = (encoded | (encoded << 1U)) ^ (0xAAAAU ^ static_cast<TEncoded>(TManchesterType::inversion_mask));
|
||||
return encoded;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Encode a 16-bit unsigned value and return the 32-bit result.
|
||||
///\param decoded The value to encode.
|
||||
///\return The Manchester encoded value.
|
||||
//*************************************************************************
|
||||
template <typename TDecoded>
|
||||
static ETL_CONSTEXPR14 typename etl::enable_if<etl::is_same<TDecoded, uint16_t>::value, typename private_manchester::encoded<TDecoded>::type>::type
|
||||
encode(TDecoded decoded)
|
||||
{
|
||||
typedef typename private_manchester::encoded<TDecoded>::type TEncoded;
|
||||
|
||||
TEncoded encoded = decoded;
|
||||
|
||||
encoded = (encoded | (encoded << 8U)) & 0x00FF00FFUL;
|
||||
encoded = (encoded | (encoded << 4U)) & 0x0F0F0F0FUL;
|
||||
encoded = (encoded | (encoded << 2U)) & 0x33333333UL;
|
||||
encoded = (encoded | (encoded << 1U)) & 0x55555555UL;
|
||||
encoded = (encoded | (encoded << 1U)) ^ (0xAAAAAAAAUL ^ static_cast<TEncoded>(TManchesterType::inversion_mask));
|
||||
return encoded;
|
||||
}
|
||||
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
//*************************************************************************
|
||||
/// Encode a 32-bit unsigned value and return the 64-bit result.
|
||||
///\param decoded The value to encode.
|
||||
///\return The Manchester encoded value.
|
||||
//*************************************************************************
|
||||
template <typename TDecoded>
|
||||
static ETL_CONSTEXPR14 typename etl::enable_if<etl::is_same<TDecoded, uint32_t>::value, typename private_manchester::encoded<TDecoded>::type>::type
|
||||
encode(TDecoded decoded)
|
||||
{
|
||||
typedef typename private_manchester::encoded<TDecoded>::type TEncoded;
|
||||
|
||||
TEncoded encoded = decoded;
|
||||
|
||||
encoded = (encoded | (encoded << 16U)) & 0x0000FFFF0000FFFFULL;
|
||||
encoded = (encoded | (encoded << 8U)) & 0x00FF00FF00FF00FFULL;
|
||||
encoded = (encoded | (encoded << 4U)) & 0x0F0F0F0F0F0F0F0FULL;
|
||||
encoded = (encoded | (encoded << 2U)) & 0x3333333333333333ULL;
|
||||
encoded = (encoded | (encoded << 1U)) & 0x5555555555555555ULL;
|
||||
encoded = (encoded | (encoded << 1U)) ^ (0xAAAAAAAAAAAAAAAAULL ^ TManchesterType::inversion_mask);
|
||||
return encoded;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Encode a span of data with the selected chunk size.
|
||||
///\param source The source data to encode.
|
||||
///\param destination The destination buffer for encoded data.
|
||||
///\tparam TChunk The chunk size for encoding (default: uint_least8_t).
|
||||
//*************************************************************************
|
||||
template <typename TChunk>
|
||||
static typename etl::enable_if<!etl::is_same<TChunk, uint_least8_t>::value, void>::type
|
||||
encode(etl::span<const uint_least8_t> decoded, etl::span<uint_least8_t> encoded)
|
||||
{
|
||||
typedef TChunk TDecoded;
|
||||
typedef typename etl::private_manchester::encoded<TChunk>::type TEncoded;
|
||||
|
||||
ETL_ASSERT(encoded.size() >= decoded.size() * 2, ETL_ERROR(manchester_invalid_size));
|
||||
ETL_ASSERT(decoded.size() % sizeof(TDecoded) == 0, ETL_ERROR(manchester_invalid_size));
|
||||
|
||||
size_t dest_index = 0;
|
||||
size_t source_index = 0;
|
||||
for (size_t i = 0; i < decoded.size() / sizeof(TDecoded); ++i)
|
||||
{
|
||||
TDecoded decoded_value = 0;
|
||||
etl::private_manchester::memcpy(&decoded_value, &decoded[source_index], sizeof(TDecoded));
|
||||
const TEncoded encoded_value = encode(decoded_value);
|
||||
etl::private_manchester::memcpy(&encoded[dest_index], &encoded_value, sizeof(TEncoded));
|
||||
|
||||
source_index += sizeof(TDecoded);
|
||||
dest_index += sizeof(TEncoded);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Encode a span of data with the minimum chunk size. This version is
|
||||
/// constexpr so that it can be used to encode data at compile time.
|
||||
///\param source The source data to encode.
|
||||
///\param destination The destination buffer for encoded data.
|
||||
///\tparam TChunk The chunk size for encoding (default: uint_least8_t).
|
||||
//*************************************************************************
|
||||
template <typename TChunk = uint_least8_t>
|
||||
static ETL_CONSTEXPR14 typename etl::enable_if<etl::is_same<TChunk, uint_least8_t>::value, void>::type encode(etl::span<const uint_least8_t> decoded, etl::span<uint_least8_t> encoded)
|
||||
{
|
||||
typedef TChunk TDecoded;
|
||||
typedef typename etl::private_manchester::encoded<TChunk>::type TEncoded;
|
||||
|
||||
ETL_ASSERT(encoded.size() >= decoded.size() * 2, ETL_ERROR(manchester_invalid_size));
|
||||
ETL_ASSERT(decoded.size() % sizeof(TDecoded) == 0, ETL_ERROR(manchester_invalid_size));
|
||||
|
||||
size_t dest_index = 0;
|
||||
size_t source_index = 0;
|
||||
for (size_t i = 0; i < decoded.size() / sizeof(TDecoded); ++i)
|
||||
{
|
||||
const TEncoded encoded_value = encode(decoded[source_index]);
|
||||
if (etl::endianness::value() == etl::endian::little)
|
||||
{
|
||||
encoded[dest_index] = static_cast<uint_least8_t>(encoded_value);
|
||||
encoded[dest_index + 1] = static_cast<uint_least8_t>(encoded_value >> CHAR_BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
encoded[dest_index] = static_cast<uint_least8_t>(encoded_value >> CHAR_BIT);
|
||||
encoded[dest_index + 1] = static_cast<uint_least8_t>(encoded_value);
|
||||
}
|
||||
|
||||
source_index += sizeof(TDecoded);
|
||||
dest_index += sizeof(TEncoded);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// Decoding functions
|
||||
//*************************************************************************
|
||||
|
||||
#if ETL_USING_8BIT_TYPES
|
||||
//*************************************************************************
|
||||
/// Decode a 16-bit value and return the 8-bit result.
|
||||
///\param encoded The value to decode.
|
||||
///\return The Manchester decoded value.
|
||||
//*************************************************************************
|
||||
template <typename TEncoded>
|
||||
static ETL_CONSTEXPR14 typename etl::enable_if<etl::is_same<TEncoded, uint16_t>::value, typename private_manchester::decoded<TEncoded>::type>::type
|
||||
decode(TEncoded encoded)
|
||||
{
|
||||
typedef typename private_manchester::decoded<TEncoded>::type TDecoded;
|
||||
|
||||
encoded = (encoded ^ (0xAAAAU ^ static_cast<TEncoded>(TManchesterType::inversion_mask))) & 0x5555U;
|
||||
encoded = (encoded | (encoded >> 1)) & 0x3333U;
|
||||
encoded = (encoded | (encoded >> 2)) & 0x0F0FU;
|
||||
return static_cast<TDecoded>(encoded | (encoded >> 4U));
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Decode a 32-bit value and return the 16-bit result.
|
||||
///\param encoded The value to decode.
|
||||
///\return The Manchester decoded value.
|
||||
//*************************************************************************
|
||||
template <typename TEncoded>
|
||||
static ETL_CONSTEXPR14 typename etl::enable_if<etl::is_same<TEncoded, uint32_t>::value, typename private_manchester::decoded<TEncoded>::type>::type
|
||||
decode(TEncoded encoded)
|
||||
{
|
||||
typedef typename private_manchester::decoded<TEncoded>::type TDecoded;
|
||||
|
||||
encoded = (encoded ^ (0xAAAAAAAAUL ^ static_cast<TEncoded>(TManchesterType::inversion_mask))) & 0x55555555UL;
|
||||
encoded = (encoded | (encoded >> 1)) & 0x33333333UL;
|
||||
encoded = (encoded | (encoded >> 2)) & 0x0F0F0F0FUL;
|
||||
encoded = (encoded | (encoded >> 4)) & 0x00FF00FFUL;
|
||||
return static_cast<TDecoded>(encoded | (encoded >> 8U));
|
||||
}
|
||||
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
//*************************************************************************
|
||||
/// Decode a 64-bit value and return the 32-bit result.
|
||||
///\param encoded The value to decode.
|
||||
///\return The Manchester decoded value.
|
||||
//*************************************************************************
|
||||
template <typename TEncoded>
|
||||
static ETL_CONSTEXPR14 typename etl::enable_if<etl::is_same<TEncoded, uint64_t>::value, typename private_manchester::decoded<TEncoded>::type>::type
|
||||
decode(TEncoded encoded)
|
||||
{
|
||||
typedef typename private_manchester::decoded<TEncoded>::type TDecoded;
|
||||
|
||||
encoded = (encoded ^ (0xAAAAAAAAAAAAAAAAULL ^ TManchesterType::inversion_mask)) & 0x5555555555555555ULL;
|
||||
encoded = (encoded | (encoded >> 1)) & 0x3333333333333333ULL;
|
||||
encoded = (encoded | (encoded >> 2)) & 0x0F0F0F0F0F0F0F0FULL;
|
||||
encoded = (encoded | (encoded >> 4)) & 0x00FF00FF00FF00FFULL;
|
||||
encoded = (encoded | (encoded >> 8)) & 0x0000FFFF0000FFFFULL;
|
||||
return static_cast<TDecoded>(encoded | (encoded >> 16U));
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Decode a span of data using specified chunk type.
|
||||
///\param source The source encoded data to decode.
|
||||
///\param destination The destination buffer for decoded data.
|
||||
///\tparam TChunk The chunk type for decoding.
|
||||
//*************************************************************************
|
||||
template <typename TChunk>
|
||||
static typename etl::enable_if<!etl::is_same<TChunk, typename private_manchester::encoded<uint_least8_t>::type>::value, void>::type
|
||||
decode(etl::span<const uint_least8_t> encoded, etl::span<uint_least8_t> decoded)
|
||||
{
|
||||
typedef typename private_manchester::decoded<TChunk>::type TDecoded;
|
||||
typedef TChunk TEncoded;
|
||||
|
||||
ETL_ASSERT(decoded.size() * 2 >= encoded.size(), ETL_ERROR(manchester_invalid_size));
|
||||
ETL_ASSERT(encoded.size() % sizeof(TChunk) == 0, ETL_ERROR(manchester_invalid_size));
|
||||
|
||||
size_t dest_index = 0;
|
||||
size_t source_index = 0;
|
||||
for (size_t i = 0; i < encoded.size() / sizeof(TEncoded); ++i)
|
||||
{
|
||||
TChunk encoded_value = 0;
|
||||
etl::private_manchester::memcpy(&encoded_value, &encoded[source_index], sizeof(TEncoded));
|
||||
const TDecoded decoded_value = decode(encoded_value);
|
||||
etl::private_manchester::memcpy(&decoded[dest_index], &decoded_value, sizeof(TDecoded));
|
||||
|
||||
source_index += sizeof(TEncoded);
|
||||
dest_index += sizeof(TDecoded);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Decode a span of data using the smallest chunk type. This version is
|
||||
/// constexpr so that it can be used to decode data at compile time.
|
||||
///\param source The source encoded data to decode.
|
||||
///\param destination The destination buffer for decoded data.
|
||||
///\tparam TChunk The chunk type for decoding (default type).
|
||||
//*************************************************************************
|
||||
template <typename TChunk = typename private_manchester::encoded<uint_least8_t>::type>
|
||||
static ETL_CONSTEXPR14 typename etl::enable_if<etl::is_same<TChunk, typename private_manchester::encoded<uint_least8_t>::type>::value, void>::type
|
||||
decode(etl::span<const uint_least8_t> encoded, etl::span<uint_least8_t> decoded)
|
||||
{
|
||||
typedef uint_least8_t TDecoded;
|
||||
|
||||
ETL_ASSERT(decoded.size() * 2 >= encoded.size(), ETL_ERROR(manchester_invalid_size));
|
||||
ETL_ASSERT(encoded.size() % sizeof(TChunk) == 0, ETL_ERROR(manchester_invalid_size));
|
||||
|
||||
size_t dest_index = 0;
|
||||
size_t source_index = 0;
|
||||
for (size_t i = 0; i < encoded.size() / sizeof(TChunk); ++i)
|
||||
{
|
||||
TChunk encoded_value{};
|
||||
if (etl::endianness::value() == etl::endian::little)
|
||||
{
|
||||
encoded_value = static_cast<TChunk>((encoded[source_index + 1] << CHAR_BIT) | encoded[source_index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
encoded_value = static_cast<TChunk>((encoded[source_index] << CHAR_BIT) | encoded[source_index + 1]);
|
||||
}
|
||||
|
||||
decoded[dest_index] = decode<TChunk>(encoded_value);
|
||||
|
||||
source_index += sizeof(TChunk);
|
||||
dest_index += sizeof(TDecoded);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// Validation functions
|
||||
//*************************************************************************
|
||||
|
||||
//*************************************************************************
|
||||
/// Validate that a value contains valid Manchester encoded data.
|
||||
///\param encoded The encoded value to validate.
|
||||
///\return True if the value is valid Manchester encoding.
|
||||
//*************************************************************************
|
||||
template <typename TChunk>
|
||||
ETL_NODISCARD static ETL_CONSTEXPR14
|
||||
typename etl::enable_if<private_manchester::is_decodable<TChunk>::value, bool>::type
|
||||
is_valid(TChunk encoded)
|
||||
{
|
||||
const TChunk mask = static_cast<TChunk>(0x5555555555555555ULL);
|
||||
return (((encoded ^ (encoded >> 1)) & mask) == mask);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Validate that a span contains valid Manchester encoded data.
|
||||
///\param encoded The span of encoded data to validate.
|
||||
///\return True if all data is valid Manchester encoding.
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD static ETL_CONSTEXPR14 bool is_valid(etl::span<const uint_least8_t> encoded)
|
||||
{
|
||||
ETL_ASSERT(encoded.size() % sizeof(uint16_t) == 0, ETL_ERROR(manchester_invalid_size));
|
||||
|
||||
for (size_t i = 0; i < encoded.size(); i += sizeof(uint16_t))
|
||||
{
|
||||
uint16_t chunk{};
|
||||
if (etl::endianness::value() == etl::endian::little)
|
||||
{
|
||||
chunk = static_cast<uint16_t>((encoded[i + 1] << CHAR_BIT) | encoded[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk = static_cast<uint16_t>((encoded[i] << CHAR_BIT) | encoded[i + 1]);
|
||||
}
|
||||
|
||||
if (!is_valid<uint16_t>(chunk))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup manchester
|
||||
/// Manchester encoder using normal encoding (no inversion).
|
||||
//***************************************************************************
|
||||
typedef manchester_base<private_manchester::manchester_type_normal> manchester;
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup manchester
|
||||
/// Manchester encoder using inverted encoding.
|
||||
//***************************************************************************
|
||||
typedef manchester_base<private_manchester::manchester_type_inverted> manchester_inverted;
|
||||
|
||||
} // namespace etl
|
||||
|
||||
#endif
|
||||
@ -216,6 +216,7 @@ add_executable(etl_tests
|
||||
test_list_shared_pool.cpp
|
||||
test_macros.cpp
|
||||
test_make_string.cpp
|
||||
test_manchester.cpp
|
||||
test_map.cpp
|
||||
test_math.cpp
|
||||
test_math_functions.cpp
|
||||
|
||||
383
test/test_manchester.cpp
Normal file
383
test/test_manchester.cpp
Normal file
@ -0,0 +1,383 @@
|
||||
#include "etl/manchester.h"
|
||||
|
||||
#include "unit_test_framework.h"
|
||||
#include <etl/algorithm.h>
|
||||
#include <etl/array.h>
|
||||
#include <etl/span.h>
|
||||
#include <utility>
|
||||
|
||||
SUITE(test_manchester)
|
||||
{
|
||||
TEST(encode_uint8_t)
|
||||
{
|
||||
CHECK_EQUAL(0xAAAA, (etl::manchester::encode<uint8_t>(0x00U)));
|
||||
CHECK_EQUAL(0x5555, (etl::manchester::encode<uint8_t>(0xFFU)));
|
||||
CHECK_EQUAL(0xAAA9, (etl::manchester::encode<uint8_t>(0x01U)));
|
||||
CHECK_EQUAL(0x6AAA, (etl::manchester::encode<uint8_t>(0x80U)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0xAAAA == etl::manchester::encode<uint8_t>(0x00U), "Compile time manchester encoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(encode_uint8_t_inverted)
|
||||
{
|
||||
CHECK_EQUAL(0x5555, (etl::manchester_inverted::encode<uint8_t>(0x00U)));
|
||||
CHECK_EQUAL(0xAAAA, (etl::manchester_inverted::encode<uint8_t>(0xFFU)));
|
||||
CHECK_EQUAL(0x5556, (etl::manchester_inverted::encode<uint8_t>(0x01U)));
|
||||
CHECK_EQUAL(0x9555, (etl::manchester_inverted::encode<uint8_t>(0x80U)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0x5555 == etl::manchester_inverted::encode<uint8_t>(0x00U), "Compile time manchester encoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(encode_uint16_t)
|
||||
{
|
||||
CHECK_EQUAL(0x5555AAAA, (etl::manchester::encode<uint16_t>(0xFF00UL)));
|
||||
CHECK_EQUAL(0x6AAAAAA9, (etl::manchester::encode<uint16_t>(0x8001UL)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0x5555AAAA == etl::manchester::encode<uint16_t>(0xFF00UL), "Compile time manchester encoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(encode_uint16_t_inverted)
|
||||
{
|
||||
CHECK_EQUAL(0xAAAA5555, (etl::manchester_inverted::encode<uint16_t>(0xFF00UL)));
|
||||
CHECK_EQUAL(0x95555556, (etl::manchester_inverted::encode<uint16_t>(0x8001UL)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0xAAAA5555 == etl::manchester_inverted::encode<uint16_t>(0xFF00UL), "Compile time manchester encoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(encode_uint32_t)
|
||||
{
|
||||
CHECK_EQUAL(0x6AAAAAA95555AAAA, (etl::manchester::encode<uint32_t>(0x8001FF00ULL)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0x6AAAAAA95555AAAA == etl::manchester::encode<uint32_t>(0x8001FF00ULL), "Compile time manchester encoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(encode_uint32_t_inverted)
|
||||
{
|
||||
CHECK_EQUAL(0x95555556AAAA5555, (etl::manchester_inverted::encode<uint32_t>(0x8001FF00ULL)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0x95555556AAAA5555 == etl::manchester_inverted::encode<uint32_t>(0x8001FF00ULL), "Compile time manchester encoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
constexpr etl::array<uint8_t, 8> manchester_encoded(etl::span<const uint_least8_t> decoded)
|
||||
{
|
||||
etl::array<uint8_t, 8> encoded{0, 0, 0, 0, 0, 0, 0, 0};
|
||||
etl::manchester::encode(decoded, encoded);
|
||||
return encoded;
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(encode_span)
|
||||
{
|
||||
constexpr etl::array<const uint8_t, 4> decoded{0x00, 0xFF, 0x01, 0x80};
|
||||
|
||||
etl::array<uint8_t, 8> encoded0;
|
||||
etl::array<uint8_t, 8> encoded1;
|
||||
etl::array<uint8_t, 8> encoded2;
|
||||
etl::array<uint8_t, 8> encoded3;
|
||||
|
||||
etl::manchester::encode(decoded, encoded0);
|
||||
etl::manchester::encode<uint8_t>(decoded, encoded1);
|
||||
etl::manchester::encode<uint16_t>(decoded, encoded2);
|
||||
etl::manchester::encode<uint32_t>(decoded, encoded3);
|
||||
|
||||
CHECK_EQUAL(0xAA, encoded0[0]);
|
||||
CHECK_EQUAL(0xAA, encoded0[1]);
|
||||
CHECK_EQUAL(0x55, encoded0[2]);
|
||||
CHECK_EQUAL(0x55, encoded0[3]);
|
||||
CHECK_EQUAL(0xA9, encoded0[4]);
|
||||
CHECK_EQUAL(0xAA, encoded0[5]);
|
||||
CHECK_EQUAL(0xAA, encoded0[6]);
|
||||
CHECK_EQUAL(0x6A, encoded0[7]);
|
||||
|
||||
CHECK_TRUE(encoded0 == encoded1);
|
||||
CHECK_TRUE(encoded0 == encoded2);
|
||||
CHECK_TRUE(encoded0 == encoded3);
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(manchester_encoded(decoded)[0] == 0xAA, "Compile time encoding on range failed");
|
||||
static_assert(manchester_encoded(decoded)[1] == 0xAA, "Compile time encoding on range failed");
|
||||
static_assert(manchester_encoded(decoded)[2] == 0x55, "Compile time encoding on range failed");
|
||||
static_assert(manchester_encoded(decoded)[3] == 0x55, "Compile time encoding on range failed");
|
||||
static_assert(manchester_encoded(decoded)[4] == 0xA9, "Compile time encoding on range failed");
|
||||
static_assert(manchester_encoded(decoded)[5] == 0xAA, "Compile time encoding on range failed");
|
||||
static_assert(manchester_encoded(decoded)[6] == 0xAA, "Compile time encoding on range failed");
|
||||
static_assert(manchester_encoded(decoded)[7] == 0x6A, "Compile time encoding on range failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(encode_span_inverted)
|
||||
{
|
||||
etl::array<const uint8_t, 4> decoded{0x00, 0xFF, 0x01, 0x80};
|
||||
|
||||
etl::array<uint8_t, 8> encoded0;
|
||||
etl::array<uint8_t, 8> encoded1;
|
||||
etl::array<uint8_t, 8> encoded2;
|
||||
etl::array<uint8_t, 8> encoded3;
|
||||
|
||||
etl::manchester_inverted::encode(decoded, encoded0);
|
||||
etl::manchester_inverted::encode<uint8_t>(decoded, encoded1);
|
||||
etl::manchester_inverted::encode<uint16_t>(decoded, encoded2);
|
||||
etl::manchester_inverted::encode<uint32_t>(decoded, encoded3);
|
||||
|
||||
CHECK_EQUAL(0x55, encoded0[0]);
|
||||
CHECK_EQUAL(0x55, encoded0[1]);
|
||||
CHECK_EQUAL(0xAA, encoded0[2]);
|
||||
CHECK_EQUAL(0xAA, encoded0[3]);
|
||||
CHECK_EQUAL(0x56, encoded0[4]);
|
||||
CHECK_EQUAL(0x55, encoded0[5]);
|
||||
CHECK_EQUAL(0x55, encoded0[6]);
|
||||
CHECK_EQUAL(0x95, encoded0[7]);
|
||||
|
||||
CHECK_TRUE(encoded0 == encoded1);
|
||||
CHECK_TRUE(encoded0 == encoded2);
|
||||
CHECK_TRUE(encoded0 == encoded3);
|
||||
}
|
||||
|
||||
TEST(encode_span_invalid_source)
|
||||
{
|
||||
etl::array<const uint8_t, 3> invalid_source{0x00, 0xFF, 0x01};
|
||||
etl::array<uint8_t, 8> valid_destination;
|
||||
|
||||
CHECK_THROW({ etl::manchester::encode<uint16_t>(invalid_source, valid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester::encode<uint32_t>(invalid_source, valid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::encode<uint16_t>(invalid_source, valid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::encode<uint32_t>(invalid_source, valid_destination); }, etl::manchester_invalid_size);
|
||||
}
|
||||
|
||||
TEST(encode_span_invalid_destination)
|
||||
{
|
||||
etl::array<const uint8_t, 4> valid_source{0x00, 0xFF, 0x01, 0x80};
|
||||
etl::array<uint8_t, 7> invalid_destination;
|
||||
|
||||
CHECK_THROW({ etl::manchester::encode<uint8_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester::encode<uint16_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester::encode<uint32_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::encode<uint8_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::encode<uint16_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::encode<uint32_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
}
|
||||
|
||||
TEST(decode_uint16_t)
|
||||
{
|
||||
CHECK_EQUAL(0x00, (etl::manchester::decode<uint16_t>(0xAAAAUL)));
|
||||
CHECK_EQUAL(0xFF, (etl::manchester::decode<uint16_t>(0x5555UL)));
|
||||
CHECK_EQUAL(0x01, (etl::manchester::decode<uint16_t>(0xAAA9UL)));
|
||||
CHECK_EQUAL(0x80, (etl::manchester::decode<uint16_t>(0x6AAAUL)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0x00 == etl::manchester::decode<uint16_t>(0xAAAAUL), "Compile time manchester decoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(decode_uint16_t_inverted)
|
||||
{
|
||||
CHECK_EQUAL(0x00, (etl::manchester_inverted::decode<uint16_t>(0x5555UL)));
|
||||
CHECK_EQUAL(0xFF, (etl::manchester_inverted::decode<uint16_t>(0xAAAAUL)));
|
||||
CHECK_EQUAL(0x01, (etl::manchester_inverted::decode<uint16_t>(0x5556UL)));
|
||||
CHECK_EQUAL(0x80, (etl::manchester_inverted::decode<uint16_t>(0x9555UL)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0x00 == etl::manchester_inverted::decode<uint16_t>(0x5555UL), "Compile time manchester decoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(decode_uint32_t)
|
||||
{
|
||||
CHECK_EQUAL(0xFF00UL, (etl::manchester::decode<uint32_t>(0x5555AAAAUL)));
|
||||
CHECK_EQUAL(0x8001UL, (etl::manchester::decode<uint32_t>(0x6AAAAAA9UL)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0xFF00UL == etl::manchester::decode<uint32_t>(0x5555AAAAUL), "Compile time manchester decoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(decode_uint32_t_inverted)
|
||||
{
|
||||
CHECK_EQUAL(0xFF00UL, (etl::manchester_inverted::decode<uint32_t>(0xAAAA5555UL)));
|
||||
CHECK_EQUAL(0x8001UL, (etl::manchester_inverted::decode<uint32_t>(0x95555556UL)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0xFF00UL == etl::manchester_inverted::decode<uint32_t>(0xAAAA5555UL), "Compile time manchester decoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(decode_uint64_t)
|
||||
{
|
||||
CHECK_EQUAL(0x8001FF00ULL, (etl::manchester::decode<uint64_t>(0x6AAAAAA95555AAAAULL)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0x8001FF00ULL == etl::manchester::decode<uint64_t>(0x6AAAAAA95555AAAAULL), "Compile time manchester decoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(decode_uint64_t_inverted)
|
||||
{
|
||||
CHECK_EQUAL(0x8001FF00ULL, (etl::manchester_inverted::decode<uint64_t>(0x95555556AAAA5555ULL)));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(0x8001FF00ULL == etl::manchester_inverted::decode<uint64_t>(0x95555556AAAA5555ULL), "Compile time manchester decoding failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
constexpr etl::array<uint8_t, 4> manchester_decoded(etl::span<const uint_least8_t> encoded)
|
||||
{
|
||||
etl::array<uint8_t, 4> decoded{0, 0, 0, 0};
|
||||
etl::manchester::decode(encoded, decoded);
|
||||
return decoded;
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(decode_span)
|
||||
{
|
||||
constexpr etl::array<const uint8_t, 8> encoded{0xAA, 0xAA, 0x55, 0x55, 0xA9, 0xAA, 0xAA, 0x6A};
|
||||
|
||||
etl::array<uint8_t, 4> decoded0;
|
||||
etl::array<uint8_t, 4> decoded1;
|
||||
etl::array<uint8_t, 4> decoded2;
|
||||
etl::array<uint8_t, 4> decoded3;
|
||||
|
||||
etl::manchester::decode(encoded, decoded0);
|
||||
etl::manchester::decode<uint16_t>(encoded, decoded1);
|
||||
etl::manchester::decode<uint32_t>(encoded, decoded2);
|
||||
etl::manchester::decode<uint64_t>(encoded, decoded3);
|
||||
|
||||
CHECK_EQUAL(0x00, decoded0[0]);
|
||||
CHECK_EQUAL(0xFF, decoded0[1]);
|
||||
CHECK_EQUAL(0x01, decoded0[2]);
|
||||
CHECK_EQUAL(0x80, decoded0[3]);
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(manchester_decoded(encoded)[0] == 0x00, "Compile time decoding on range failed");
|
||||
static_assert(manchester_decoded(encoded)[1] == 0xFF, "Compile time decoding on range failed");
|
||||
static_assert(manchester_decoded(encoded)[2] == 0x01, "Compile time decoding on range failed");
|
||||
static_assert(manchester_decoded(encoded)[3] == 0x80, "Compile time decoding on range failed");
|
||||
#endif
|
||||
|
||||
CHECK_TRUE(decoded0 == decoded1);
|
||||
CHECK_TRUE(decoded0 == decoded2);
|
||||
CHECK_TRUE(decoded0 == decoded3);
|
||||
}
|
||||
|
||||
TEST(decode_span_inverted)
|
||||
{
|
||||
etl::array<const uint8_t, 8> encoded{0x55, 0x55, 0xAA, 0xAA, 0x56, 0x55, 0x55, 0x95};
|
||||
|
||||
etl::array<uint8_t, 4> decoded0;
|
||||
etl::array<uint8_t, 4> decoded1;
|
||||
etl::array<uint8_t, 4> decoded2;
|
||||
etl::array<uint8_t, 4> decoded3;
|
||||
|
||||
etl::manchester_inverted::decode(encoded, decoded0);
|
||||
etl::manchester_inverted::decode<uint16_t>(encoded, decoded1);
|
||||
etl::manchester_inverted::decode<uint32_t>(encoded, decoded2);
|
||||
etl::manchester_inverted::decode<uint64_t>(encoded, decoded3);
|
||||
|
||||
CHECK_EQUAL(0x00, decoded0[0]);
|
||||
CHECK_EQUAL(0xFF, decoded0[1]);
|
||||
CHECK_EQUAL(0x01, decoded0[2]);
|
||||
CHECK_EQUAL(0x80, decoded0[3]);
|
||||
|
||||
CHECK_TRUE(decoded0 == decoded1);
|
||||
CHECK_TRUE(decoded0 == decoded2);
|
||||
CHECK_TRUE(decoded0 == decoded3);
|
||||
}
|
||||
|
||||
TEST(decode_span_invalid_source)
|
||||
{
|
||||
etl::array<const uint8_t, 7> invalid_source{0x55, 0x55, 0xAA, 0xAA, 0x56, 0x55, 0x55};
|
||||
etl::array<uint8_t, 4> valid_destination;
|
||||
|
||||
CHECK_THROW({ etl::manchester::decode<uint16_t>(invalid_source, valid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester::decode<uint32_t>(invalid_source, valid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester::decode<uint64_t>(invalid_source, valid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::decode<uint16_t>(invalid_source, valid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::decode<uint32_t>(invalid_source, valid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::decode<uint64_t>(invalid_source, valid_destination); }, etl::manchester_invalid_size);
|
||||
}
|
||||
|
||||
TEST(decode_span_invalid_destination)
|
||||
{
|
||||
etl::array<const uint8_t, 8> valid_source{0x55, 0x55, 0xAA, 0xAA, 0x56, 0x55, 0x55, 0x95};
|
||||
etl::array<uint8_t, 3> invalid_destination;
|
||||
|
||||
CHECK_THROW({ etl::manchester::decode<uint16_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester::decode<uint32_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester::decode<uint64_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::decode<uint16_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::decode<uint32_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
CHECK_THROW({ etl::manchester_inverted::decode<uint64_t>(valid_source, invalid_destination); }, etl::manchester_invalid_size);
|
||||
}
|
||||
|
||||
TEST(valid16)
|
||||
{
|
||||
CHECK_TRUE(etl::manchester::is_valid<uint16_t>(0xAAAAUL));
|
||||
CHECK_TRUE(etl::manchester_inverted::is_valid<uint16_t>(0xAAAAUL));
|
||||
CHECK_FALSE(etl::manchester::is_valid<uint16_t>(0xAAA8UL));
|
||||
CHECK_FALSE(etl::manchester_inverted::is_valid<uint16_t>(0xAAA8UL));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(etl::manchester::is_valid<uint16_t>(0xAAAAUL), "Compile time manchester validity check failed");
|
||||
static_assert(etl::manchester_inverted::is_valid<uint16_t>(0xAAAAUL), "Compile time manchester validity check failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(valid32)
|
||||
{
|
||||
CHECK_TRUE(etl::manchester::is_valid<uint32_t>(0xAAAAAAAAUL));
|
||||
CHECK_TRUE(etl::manchester_inverted::is_valid<uint32_t>(0xAAAAAAAAUL));
|
||||
CHECK_FALSE(etl::manchester::is_valid<uint32_t>(0xAAAAAAA8UL));
|
||||
CHECK_FALSE(etl::manchester_inverted::is_valid<uint32_t>(0xAAAAAAA8UL));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(etl::manchester::is_valid<uint32_t>(0xAAAAAAAAUL), "Compile time manchester validity check failed");
|
||||
static_assert(etl::manchester_inverted::is_valid<uint32_t>(0xAAAAAAAAUL), "Compile time manchester validity check failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(valid64)
|
||||
{
|
||||
CHECK_TRUE(etl::manchester::is_valid<uint64_t>(0xAAAAAAAAAAAAAAAAULL));
|
||||
CHECK_TRUE(etl::manchester_inverted::is_valid<uint64_t>(0xAAAAAAAAAAAAAAAAULL));
|
||||
CHECK_FALSE(etl::manchester::is_valid<uint64_t>(0xAAAAAAAAAAAAAAA8ULL));
|
||||
CHECK_FALSE(etl::manchester_inverted::is_valid<uint64_t>(0xAAAAAAAAAAAAAAA8ULL));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(etl::manchester::is_valid<uint64_t>(0xAAAAAAAAAAAAAAAAULL), "Compile time manchester validity check failed");
|
||||
static_assert(etl::manchester_inverted::is_valid<uint64_t>(0xAAAAAAAAAAAAAAAAULL), "Compile time manchester validity check failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(valid_span)
|
||||
{
|
||||
constexpr etl::array<uint8_t, 8> encoded1{0xAA, 0xAA, 0x55, 0x55, 0xA9, 0xAA, 0xAA, 0x6A};
|
||||
constexpr etl::array<uint8_t, 8> encoded2{0xAA, 0xAA, 0x55, 0x55, 0xA9, 0xAA, 0xAB, 0x6A};
|
||||
|
||||
CHECK_TRUE(etl::manchester::is_valid(encoded1));
|
||||
CHECK_FALSE(etl::manchester::is_valid(encoded2));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
static_assert(etl::manchester::is_valid(encoded1), "Compile time manchester validity check failed");
|
||||
static_assert(!etl::manchester::is_valid(encoded2), "Compile time manchester validity check failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(valid_span_on_invalid_source)
|
||||
{
|
||||
constexpr etl::array<uint8_t, 7> invalid_source{0xAA, 0xAA, 0x55, 0x55, 0xA9, 0xAA, 0xAA};
|
||||
CHECK_THROW({ std::ignore = etl::manchester::is_valid(invalid_source); }, etl::manchester_invalid_size);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user