mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Manchester big endian support (#1353)
* 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 * #1258 Manchester coding * Add manchester documentation * #1258 Manchester coding * Preparation for GitHub pages * #1324 Manchester documentation * Some small fixes * Print test names at test time (#1343) * IGN-280 biphasic amplitude as float * Add big-endian devcontainer * manchester * fixed the configuration to work with GitHub Codespaces. The changes use cross-compilation with QEMU emulation instead of trying to use a native s390x container. * manchester * Made manchester work for big-endian * Some updates to the container * Manchester big-endian support * Cleanup * Manchester big-endian support * add sourcedirectory * Enable running with ctest * Manchester big-endian support * Update documentation * Manchester big-endian support * QA * Manchester big-endian support * QA * Enable testing with ctest with cross-compiler (#5) * Enable testing with ctest and with cross-compiler * Clean up includes in manchester.h --------- Co-authored-by: Timon Zijnge <timon.zijnge@imec.nl> --------- Co-authored-by: Timon Zijnge <timon.zijnge@imec.nl> Co-authored-by: Roland Reichwein <Roland.Reichwein@bmw.de>
This commit is contained in:
parent
d5fc8d0cd1
commit
2f6a3e04aa
40
.devcontainer/s390x/Dockerfile
Normal file
40
.devcontainer/s390x/Dockerfile
Normal file
@ -0,0 +1,40 @@
|
||||
# s390x Big-Endian Test Environment for ETL
|
||||
# Uses QEMU user-mode emulation to run s390x binaries on x64 host
|
||||
FROM debian:trixie
|
||||
|
||||
# Avoid prompts from apt
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Install QEMU user-mode emulation and s390x cross-compilation tools
|
||||
RUN dpkg --add-architecture s390x && \
|
||||
apt-get update && apt-get install -y --no-install-recommends\
|
||||
qemu-user-static \
|
||||
qemu-user \
|
||||
binfmt-support \
|
||||
gcc-s390x-linux-gnu \
|
||||
g++-s390x-linux-gnu \
|
||||
cmake \
|
||||
make \
|
||||
ninja-build \
|
||||
git \
|
||||
wget \
|
||||
file \
|
||||
libc6:s390x \
|
||||
libstdc++6:s390x \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /workspaces/etl
|
||||
|
||||
# Verify QEMU and cross-compilation setup
|
||||
RUN echo "=== Host Architecture ===" && \
|
||||
uname -m && \
|
||||
echo "" && \
|
||||
echo "=== s390x Cross Compiler ===" && \
|
||||
s390x-linux-gnu-gcc --version && \
|
||||
echo "" && \
|
||||
echo "=== QEMU s390x ===" && \
|
||||
qemu-s390x-static --version | head -n1
|
||||
|
||||
# Default command
|
||||
CMD ["/bin/bash"]
|
||||
29
.devcontainer/s390x/devcontainer.json
Normal file
29
.devcontainer/s390x/devcontainer.json
Normal file
@ -0,0 +1,29 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
|
||||
{
|
||||
"name": "s390x Big Endian (Debian)",
|
||||
"build": {
|
||||
"dockerfile": "./Dockerfile",
|
||||
"context": "."
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.cmake-tools"
|
||||
],
|
||||
"settings": {
|
||||
"cmake.sourceDirectory": "${workspaceFolder}/test",
|
||||
"cmake.configureArgs": [
|
||||
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/s390x/toolchain-s390x.cmake",
|
||||
"-DBUILD_TESTS=ON",
|
||||
"-DNO_STL=OFF",
|
||||
"-DETL_CXX_STANDARD=17"
|
||||
],
|
||||
"cmake.buildDirectory": "${workspaceFolder}/build-s390x",
|
||||
"cmake.generator": "Ninja"
|
||||
}
|
||||
}
|
||||
},
|
||||
"remoteUser": "root"
|
||||
}
|
||||
21
.devcontainer/s390x/toolchain-s390x.cmake
Normal file
21
.devcontainer/s390x/toolchain-s390x.cmake
Normal file
@ -0,0 +1,21 @@
|
||||
# CMake toolchain file for s390x cross-compilation
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR s390x)
|
||||
|
||||
# Specify the cross compiler
|
||||
set(CMAKE_C_COMPILER s390x-linux-gnu-gcc)
|
||||
set(CMAKE_CXX_COMPILER s390x-linux-gnu-g++)
|
||||
set(CMAKE_AR s390x-linux-gnu-ar)
|
||||
set(CMAKE_RANLIB s390x-linux-gnu-ranlib)
|
||||
set(CMAKE_STRIP s390x-linux-gnu-strip)
|
||||
|
||||
# Search for programs in the build host directories
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
|
||||
# For libraries and headers in the target directories
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
# Set QEMU for running tests
|
||||
set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-s390x-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries")
|
||||
@ -13,8 +13,9 @@ Efficient Manchester encoding and decoding of data. The Manchester code represen
|
||||
- Normal and inverted Manchester encoding
|
||||
- Support for multiple encoding chunk sizes: 8-bit, 16-bit and 32-bit
|
||||
- Span-based operations or chunk-based operations
|
||||
- Constexpr functions for compile-time encoding/decoding (8-bit chunk size only)
|
||||
- Constexpr functions for compile-time encoding/decoding
|
||||
- Validation of encoded data
|
||||
- Chunked span I/O uses little-endian byte order for multi-byte chunks, independent of host platform endianness
|
||||
|
||||
## Algorithm background
|
||||
|
||||
|
||||
@ -32,10 +32,8 @@ SOFTWARE.
|
||||
#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
|
||||
@ -172,18 +170,37 @@ namespace etl
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// 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
|
||||
/// Read a multi-byte value from a span in little-endian byte order.
|
||||
///\tparam T The type to read.
|
||||
///\param bytes The span to read from.
|
||||
///\param index The starting index in the span.
|
||||
///\return The value read from the span.
|
||||
//*************************************************************************
|
||||
inline void* memcpy(void* dest, const void* src, std::size_t count) ETL_NOEXCEPT
|
||||
template <typename T>
|
||||
static ETL_CONSTEXPR14 T read_little_endian(etl::span<const uint_least8_t> bytes, size_t index)
|
||||
{
|
||||
#if ETL_USING_BUILTIN_MEMCPY
|
||||
return __builtin_memcpy(dest, src, count);
|
||||
#else
|
||||
return ::memcpy(dest, src, count);
|
||||
#endif
|
||||
T value = 0;
|
||||
for (size_t j = 0; j < sizeof(T); ++j)
|
||||
{
|
||||
value |= static_cast<T>(bytes[index + j]) << (j * CHAR_BIT);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Write a multi-byte value to a span in little-endian byte order.
|
||||
///\tparam T The type to write.
|
||||
///\param bytes The span to write to.
|
||||
///\param index The starting index in the span.
|
||||
///\param value The value to write.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
static ETL_CONSTEXPR14 void write_little_endian(etl::span<uint_least8_t> bytes, size_t index, T value)
|
||||
{
|
||||
for (size_t j = 0; j < sizeof(T); ++j)
|
||||
{
|
||||
bytes[index + j] = static_cast<uint_least8_t>(value >> (j * CHAR_BIT));
|
||||
}
|
||||
}
|
||||
} // namespace private_manchester
|
||||
|
||||
@ -297,44 +314,13 @@ namespace etl
|
||||
#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.
|
||||
/// Encode a span of data with the specified 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 = 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)
|
||||
static ETL_CONSTEXPR14 void 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;
|
||||
@ -346,17 +332,9 @@ namespace etl
|
||||
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);
|
||||
}
|
||||
const TDecoded decoded_value = private_manchester::read_little_endian<TDecoded>(decoded, source_index);
|
||||
const TEncoded encoded_value = encode(decoded_value);
|
||||
private_manchester::write_little_endian<TEncoded>(encoded, dest_index, encoded_value);
|
||||
|
||||
source_index += sizeof(TDecoded);
|
||||
dest_index += sizeof(TEncoded);
|
||||
@ -426,14 +404,13 @@ namespace etl
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Decode a span of data using specified chunk type.
|
||||
/// Decode a span of data using the 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.
|
||||
///\tparam TChunk The chunk type for decoding (default: uint16_t).
|
||||
//*************************************************************************
|
||||
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)
|
||||
template <typename TChunk = typename private_manchester::encoded<uint_least8_t>::type>
|
||||
static ETL_CONSTEXPR14 void 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;
|
||||
@ -445,53 +422,15 @@ namespace etl
|
||||
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 TEncoded encoded_value = private_manchester::read_little_endian<TEncoded>(encoded, source_index);
|
||||
const TDecoded decoded_value = decode(encoded_value);
|
||||
etl::private_manchester::memcpy(&decoded[dest_index], &decoded_value, sizeof(TDecoded));
|
||||
private_manchester::write_little_endian<TDecoded>(decoded, dest_index, decoded_value);
|
||||
|
||||
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
|
||||
//*************************************************************************
|
||||
@ -521,15 +460,7 @@ namespace etl
|
||||
|
||||
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]);
|
||||
}
|
||||
const uint16_t chunk = private_manchester::read_little_endian<uint16_t>(encoded, i);
|
||||
|
||||
if (!is_valid<uint16_t>(chunk))
|
||||
{
|
||||
|
||||
@ -532,8 +532,9 @@ target_include_directories(etl_tests
|
||||
add_subdirectory(UnitTest++)
|
||||
target_link_libraries(etl_tests PRIVATE UnitTestpp ${EXTRA_LINK_LIBS})
|
||||
|
||||
enable_testing()
|
||||
# Enable the 'make test' CMake target using the executable defined above
|
||||
add_test(etl_unit_tests etl_tests)
|
||||
add_test(NAME etl_unit_tests COMMAND etl_tests)
|
||||
|
||||
# Since ctest will only show you the results of the single executable
|
||||
# define a target that will output all of the failing or passing tests
|
||||
|
||||
@ -71,12 +71,26 @@ SUITE(test_manchester)
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
constexpr etl::array<uint8_t, 8> manchester_encoded(etl::span<const uint_least8_t> decoded)
|
||||
constexpr etl::array<uint8_t, 8> manchester_encoded_uint8(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;
|
||||
}
|
||||
|
||||
constexpr etl::array<uint8_t, 8> manchester_encoded_uint16(etl::span<const uint_least8_t> decoded)
|
||||
{
|
||||
etl::array<uint8_t, 8> encoded{0, 0, 0, 0, 0, 0, 0, 0};
|
||||
etl::manchester::encode<uint16_t>(decoded, encoded);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
constexpr etl::array<uint8_t, 8> manchester_encoded_uint32(etl::span<const uint_least8_t> decoded)
|
||||
{
|
||||
etl::array<uint8_t, 8> encoded{0, 0, 0, 0, 0, 0, 0, 0};
|
||||
etl::manchester::encode<uint32_t>(decoded, encoded);
|
||||
return encoded;
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(encode_span)
|
||||
@ -105,18 +119,41 @@ SUITE(test_manchester)
|
||||
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_constexpr)
|
||||
{
|
||||
constexpr etl::array<const uint8_t, 4> decoded{0x00, 0xFF, 0x01, 0x80};
|
||||
|
||||
static_assert(manchester_encoded_uint8(decoded)[0] == 0xAA, "Compile time encoding with uint8_t failed");
|
||||
static_assert(manchester_encoded_uint8(decoded)[1] == 0xAA, "Compile time encoding with uint8_t failed");
|
||||
static_assert(manchester_encoded_uint8(decoded)[2] == 0x55, "Compile time encoding with uint8_t failed");
|
||||
static_assert(manchester_encoded_uint8(decoded)[3] == 0x55, "Compile time encoding with uint8_t failed");
|
||||
static_assert(manchester_encoded_uint8(decoded)[4] == 0xA9, "Compile time encoding with uint8_t failed");
|
||||
static_assert(manchester_encoded_uint8(decoded)[5] == 0xAA, "Compile time encoding with uint8_t failed");
|
||||
static_assert(manchester_encoded_uint8(decoded)[6] == 0xAA, "Compile time encoding with uint8_t failed");
|
||||
static_assert(manchester_encoded_uint8(decoded)[7] == 0x6A, "Compile time encoding with uint8_t failed");
|
||||
|
||||
static_assert(manchester_encoded_uint16(decoded)[0] == 0xAA, "Compile time encoding with uint16_t failed");
|
||||
static_assert(manchester_encoded_uint16(decoded)[1] == 0xAA, "Compile time encoding with uint16_t failed");
|
||||
static_assert(manchester_encoded_uint16(decoded)[2] == 0x55, "Compile time encoding with uint16_t failed");
|
||||
static_assert(manchester_encoded_uint16(decoded)[3] == 0x55, "Compile time encoding with uint16_t failed");
|
||||
static_assert(manchester_encoded_uint16(decoded)[4] == 0xA9, "Compile time encoding with uint16_t failed");
|
||||
static_assert(manchester_encoded_uint16(decoded)[5] == 0xAA, "Compile time encoding with uint16_t failed");
|
||||
static_assert(manchester_encoded_uint16(decoded)[6] == 0xAA, "Compile time encoding with uint16_t failed");
|
||||
static_assert(manchester_encoded_uint16(decoded)[7] == 0x6A, "Compile time encoding with uint16_t failed");
|
||||
|
||||
static_assert(manchester_encoded_uint32(decoded)[0] == 0xAA, "Compile time encoding with uint32_t failed");
|
||||
static_assert(manchester_encoded_uint32(decoded)[1] == 0xAA, "Compile time encoding with uint32_t failed");
|
||||
static_assert(manchester_encoded_uint32(decoded)[2] == 0x55, "Compile time encoding with uint32_t failed");
|
||||
static_assert(manchester_encoded_uint32(decoded)[3] == 0x55, "Compile time encoding with uint32_t failed");
|
||||
static_assert(manchester_encoded_uint32(decoded)[4] == 0xA9, "Compile time encoding with uint32_t failed");
|
||||
static_assert(manchester_encoded_uint32(decoded)[5] == 0xAA, "Compile time encoding with uint32_t failed");
|
||||
static_assert(manchester_encoded_uint32(decoded)[6] == 0xAA, "Compile time encoding with uint32_t failed");
|
||||
static_assert(manchester_encoded_uint32(decoded)[7] == 0x6A, "Compile time encoding with uint32_t failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(encode_span_inverted)
|
||||
{
|
||||
@ -233,12 +270,26 @@ SUITE(test_manchester)
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
constexpr etl::array<uint8_t, 4> manchester_decoded(etl::span<const uint_least8_t> encoded)
|
||||
constexpr etl::array<uint8_t, 4> manchester_decoded_uint16(etl::span<const uint_least8_t> encoded)
|
||||
{
|
||||
etl::array<uint8_t, 4> decoded{0, 0, 0, 0};
|
||||
etl::manchester::decode(encoded, decoded);
|
||||
return decoded;
|
||||
}
|
||||
|
||||
constexpr etl::array<uint8_t, 4> manchester_decoded_uint32(etl::span<const uint_least8_t> encoded)
|
||||
{
|
||||
etl::array<uint8_t, 4> decoded{0, 0, 0, 0};
|
||||
etl::manchester::decode<uint32_t>(encoded, decoded);
|
||||
return decoded;
|
||||
}
|
||||
|
||||
constexpr etl::array<uint8_t, 4> manchester_decoded_uint64(etl::span<const uint_least8_t> encoded)
|
||||
{
|
||||
etl::array<uint8_t, 4> decoded{0, 0, 0, 0};
|
||||
etl::manchester::decode<uint64_t>(encoded, decoded);
|
||||
return decoded;
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(decode_span)
|
||||
@ -260,18 +311,33 @@ SUITE(test_manchester)
|
||||
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);
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
TEST(decode_span_constexpr)
|
||||
{
|
||||
constexpr etl::array<const uint8_t, 8> encoded{0xAA, 0xAA, 0x55, 0x55, 0xA9, 0xAA, 0xAA, 0x6A};
|
||||
|
||||
static_assert(manchester_decoded_uint16(encoded)[0] == 0x00, "Compile time decoding with uint16_t failed");
|
||||
static_assert(manchester_decoded_uint16(encoded)[1] == 0xFF, "Compile time decoding with uint16_t failed");
|
||||
static_assert(manchester_decoded_uint16(encoded)[2] == 0x01, "Compile time decoding with uint16_t failed");
|
||||
static_assert(manchester_decoded_uint16(encoded)[3] == 0x80, "Compile time decoding with uint16_t failed");
|
||||
|
||||
static_assert(manchester_decoded_uint32(encoded)[0] == 0x00, "Compile time decoding with uint32_t failed");
|
||||
static_assert(manchester_decoded_uint32(encoded)[1] == 0xFF, "Compile time decoding with uint32_t failed");
|
||||
static_assert(manchester_decoded_uint32(encoded)[2] == 0x01, "Compile time decoding with uint32_t failed");
|
||||
static_assert(manchester_decoded_uint32(encoded)[3] == 0x80, "Compile time decoding with uint32_t failed");
|
||||
|
||||
static_assert(manchester_decoded_uint64(encoded)[0] == 0x00, "Compile time decoding with uint64_t failed");
|
||||
static_assert(manchester_decoded_uint64(encoded)[1] == 0xFF, "Compile time decoding with uint64_t failed");
|
||||
static_assert(manchester_decoded_uint64(encoded)[2] == 0x01, "Compile time decoding with uint64_t failed");
|
||||
static_assert(manchester_decoded_uint64(encoded)[3] == 0x80, "Compile time decoding with uint64_t failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(decode_span_inverted)
|
||||
{
|
||||
etl::array<const uint8_t, 8> encoded{0x55, 0x55, 0xAA, 0xAA, 0x56, 0x55, 0x55, 0x95};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user