Embedded Template Library 1.0
Loading...
Searching...
No Matches
manchester.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2026 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_MANCHESTER_INCLUDED
32#define ETL_MANCHESTER_INCLUDED
33
34#include "platform.h"
35#include "span.h"
36#include "static_assert.h"
37
41
42namespace etl
43{
44 namespace private_manchester
45 {
46 //*************************************************************************
49 //*************************************************************************
50 template <typename TChunk>
52 {
53 static const bool value =
54#if ETL_USING_8BIT_TYPES
55 etl::is_same<TChunk, uint8_t>::value ||
56#endif
57 etl::is_same<TChunk, uint16_t>::value
58#if ETL_USING_64BIT_TYPES
59 || etl::is_same<TChunk, uint32_t>::value
60#endif
61 ;
62 };
63
64 //*************************************************************************
67 //*************************************************************************
68 template <typename TChunk>
70 {
71 static const bool value =
72#if ETL_USING_8BIT_TYPES
73 etl::is_same<TChunk, uint16_t>::value ||
74#endif
75 etl::is_same<TChunk, uint32_t>::value
76#if ETL_USING_64BIT_TYPES
77 || etl::is_same<TChunk, uint64_t>::value
78#endif
79 ;
80 };
81
82 //*************************************************************************
87 //*************************************************************************
88 template <typename T>
89 struct encoded
90 {
91 ETL_STATIC_ASSERT(sizeof(T) == 0, "Manchester encoding type should be one of [uint8_t, uint16_t, uint32_t]");
92 };
93
94#if ETL_USING_8BIT_TYPES
95 template <>
96 struct encoded<uint8_t>
97 {
98 typedef uint16_t type;
99 };
100#endif
101
102 template <>
103 struct encoded<uint16_t>
104 {
105 typedef uint32_t type;
106 };
107
108#if ETL_USING_64BIT_TYPES
109 template <>
110 struct encoded<uint32_t>
111 {
112 typedef uint64_t type;
113 };
114#endif
115
116 //*************************************************************************
121 //*************************************************************************
122 template <typename T>
123 struct decoded
124 {
125 ETL_STATIC_ASSERT(sizeof(T) == 0, "Manchester decoding type should be one of [uint16_t, uint32_t, uint64_t]");
126 };
127
128#if ETL_USING_64BIT_TYPES
129 template <>
130 struct decoded<uint16_t>
131 {
132 typedef uint8_t type;
133 };
134#endif
135
136 template <>
137 struct decoded<uint32_t>
138 {
139 typedef uint16_t type;
140 };
141
142#if ETL_USING_64BIT_TYPES
143 template <>
144 struct decoded<uint64_t>
145 {
146 typedef uint32_t type;
147 };
148#endif
149
150 //*************************************************************************
152 //*************************************************************************
154 {
155#if ETL_USING_64BIT_TYPES
156 static const uint64_t inversion_mask = 0x0000000000000000ULL;
157#else
158 static const uint32_t inversion_mask = 0x00000000UL;
159#endif
160 };
161
162 //*************************************************************************
164 //*************************************************************************
166 {
167#if ETL_USING_64BIT_TYPES
168 static const uint64_t inversion_mask = 0xFFFFFFFFFFFFFFFFULL;
169#else
170 static const uint32_t inversion_mask = 0xFFFFFFFFUL;
171#endif
172 };
173
174 //*************************************************************************
180 //*************************************************************************
181 template <typename T>
182 static ETL_CONSTEXPR14 T read_little_endian(etl::span<const uint_least8_t> bytes, size_t index)
183 {
184 T value = 0;
185 for (size_t j = 0; j < sizeof(T); ++j)
186 {
187 value |= static_cast<T>(bytes[index + j]) << (j * CHAR_BIT);
188 }
189 return value;
190 }
191
192 //*************************************************************************
198 //*************************************************************************
199 template <typename T>
200 static ETL_CONSTEXPR14 void write_little_endian(etl::span<uint_least8_t> bytes, size_t index, T value)
201 {
202 for (size_t j = 0; j < sizeof(T); ++j)
203 {
204 bytes[index + j] = static_cast<uint_least8_t>(value >> (j * CHAR_BIT));
205 }
206 }
207 } // namespace private_manchester
208
209 //***************************************************************************
211 //***************************************************************************
212 class manchester_exception : public etl::exception
213 {
214 public:
215
216 manchester_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
217 : exception(reason_, file_name_, line_number_)
218 {
219 }
220 };
221
222 //***************************************************************************
224 //***************************************************************************
225 class manchester_invalid_size : public etl::manchester_exception
226 {
227 public:
228
229 manchester_invalid_size(string_type file_name_, numeric_type line_number_)
230 : etl::manchester_exception("manchester:size", file_name_, line_number_)
231 {
232 }
233 };
234
235 //***************************************************************************
239 //***************************************************************************
240 template <typename TManchesterType>
242 {
243 ETL_STATIC_ASSERT((etl::is_same<TManchesterType, private_manchester::manchester_type_normal>::value
244 || etl::is_same<TManchesterType, private_manchester::manchester_type_inverted>::value),
245 "TManchesterType must be manchester_type_normal or manchester_type_inverted");
246
247 ETL_STATIC_ASSERT(CHAR_BIT == etl::numeric_limits<uint_least8_t>::digits,
248 "Manchester requires uint_least8_t to have the same number of bits as CHAR (CHAR_BITS)");
249
250 //*************************************************************************
251 // Encoding functions
252 //*************************************************************************
253
254#if ETL_USING_8BIT_TYPES
255 //*************************************************************************
259 //*************************************************************************
260 template <typename TDecoded>
261 static
262 ETL_CONSTEXPR14 typename etl::enable_if< etl::is_same<TDecoded, uint8_t>::value, typename private_manchester::encoded<TDecoded>::type>::type
263 encode(TDecoded decoded)
264 {
265 typedef typename private_manchester::encoded<TDecoded>::type TEncoded;
266
267 TEncoded encoded = decoded;
268
269 encoded = static_cast<TEncoded>((static_cast<unsigned int>(encoded) | (static_cast<unsigned int>(encoded) << 4U)) & 0x0F0FU);
270 encoded = static_cast<TEncoded>((static_cast<unsigned int>(encoded) | (static_cast<unsigned int>(encoded) << 2U)) & 0x3333U);
271 encoded = static_cast<TEncoded>((static_cast<unsigned int>(encoded) | (static_cast<unsigned int>(encoded) << 1U)) & 0x5555U);
272 encoded = static_cast<TEncoded>((static_cast<unsigned int>(encoded) | (static_cast<unsigned int>(encoded) << 1U))
273 ^ (0xAAAAU ^ static_cast<unsigned int>(TManchesterType::inversion_mask)));
274 return encoded;
275 }
276#endif
277
278 //*************************************************************************
282 //*************************************************************************
283 template <typename TDecoded>
284 static
285 ETL_CONSTEXPR14 typename etl::enable_if< etl::is_same<TDecoded, uint16_t>::value, typename private_manchester::encoded<TDecoded>::type>::type
286 encode(TDecoded decoded)
287 {
288 typedef typename private_manchester::encoded<TDecoded>::type TEncoded;
289
290 TEncoded encoded = decoded;
291
292 encoded = (encoded | (encoded << 8U)) & 0x00FF00FFUL;
293 encoded = (encoded | (encoded << 4U)) & 0x0F0F0F0FUL;
294 encoded = (encoded | (encoded << 2U)) & 0x33333333UL;
295 encoded = (encoded | (encoded << 1U)) & 0x55555555UL;
296 encoded = (encoded | (encoded << 1U)) ^ (0xAAAAAAAAUL ^ static_cast<TEncoded>(TManchesterType::inversion_mask));
297 return encoded;
298 }
299
300#if ETL_USING_64BIT_TYPES
301 //*************************************************************************
305 //*************************************************************************
306 template <typename TDecoded>
307 static
308 ETL_CONSTEXPR14 typename etl::enable_if< etl::is_same<TDecoded, uint32_t>::value, typename private_manchester::encoded<TDecoded>::type>::type
309 encode(TDecoded decoded)
310 {
311 typedef typename private_manchester::encoded<TDecoded>::type TEncoded;
312
313 TEncoded encoded = decoded;
314
315 encoded = (encoded | (encoded << 16U)) & 0x0000FFFF0000FFFFULL;
316 encoded = (encoded | (encoded << 8U)) & 0x00FF00FF00FF00FFULL;
317 encoded = (encoded | (encoded << 4U)) & 0x0F0F0F0F0F0F0F0FULL;
318 encoded = (encoded | (encoded << 2U)) & 0x3333333333333333ULL;
319 encoded = (encoded | (encoded << 1U)) & 0x5555555555555555ULL;
320 encoded = (encoded | (encoded << 1U)) ^ (0xAAAAAAAAAAAAAAAAULL ^ TManchesterType::inversion_mask);
321 return encoded;
322 }
323#endif
324
325 //*************************************************************************
330 //*************************************************************************
331 template <typename TChunk = uint_least8_t>
332 static ETL_CONSTEXPR14 void encode(etl::span<const uint_least8_t> decoded, etl::span<uint_least8_t> encoded)
333 {
334 typedef TChunk TDecoded;
335 typedef typename etl::private_manchester::encoded<TChunk>::type TEncoded;
336
337 ETL_ASSERT(encoded.size() >= decoded.size() * 2, ETL_ERROR(manchester_invalid_size));
338 ETL_ASSERT(decoded.size() % sizeof(TDecoded) == 0, ETL_ERROR(manchester_invalid_size));
339
340 size_t dest_index = 0;
341 size_t source_index = 0;
342 for (size_t i = 0; i < decoded.size() / sizeof(TDecoded); ++i)
343 {
344 const TDecoded decoded_value = private_manchester::read_little_endian<TDecoded>(decoded, source_index);
345 const TEncoded encoded_value = encode(decoded_value);
346 private_manchester::write_little_endian<TEncoded>(encoded, dest_index, encoded_value);
347
348 source_index += sizeof(TDecoded);
349 dest_index += sizeof(TEncoded);
350 }
351 }
352
353 //*************************************************************************
354 // Decoding functions
355 //*************************************************************************
356
357#if ETL_USING_8BIT_TYPES
358 //*************************************************************************
362 //*************************************************************************
363 template <typename TEncoded>
364 static
365 ETL_CONSTEXPR14 typename etl::enable_if< etl::is_same<TEncoded, uint16_t>::value, typename private_manchester::decoded<TEncoded>::type>::type
366 decode(TEncoded encoded)
367 {
368 typedef typename private_manchester::decoded<TEncoded>::type TDecoded;
369
370 encoded = static_cast<TEncoded>((static_cast<unsigned int>(encoded) ^ (0xAAAAU ^ static_cast<unsigned int>(TManchesterType::inversion_mask)))
371 & 0x5555U);
372 encoded = static_cast<TEncoded>((static_cast<unsigned int>(encoded) | (static_cast<unsigned int>(encoded) >> 1)) & 0x3333U);
373 encoded = static_cast<TEncoded>((static_cast<unsigned int>(encoded) | (static_cast<unsigned int>(encoded) >> 2)) & 0x0F0FU);
374 return static_cast<TDecoded>(static_cast<unsigned int>(encoded) | (static_cast<unsigned int>(encoded) >> 4U));
375 }
376#endif
377
378 //*************************************************************************
382 //*************************************************************************
383 template <typename TEncoded>
384 static
385 ETL_CONSTEXPR14 typename etl::enable_if< etl::is_same<TEncoded, uint32_t>::value, typename private_manchester::decoded<TEncoded>::type>::type
386 decode(TEncoded encoded)
387 {
388 typedef typename private_manchester::decoded<TEncoded>::type TDecoded;
389
390 encoded = (encoded ^ (0xAAAAAAAAUL ^ static_cast<TEncoded>(TManchesterType::inversion_mask))) & 0x55555555UL;
391 encoded = (encoded | (encoded >> 1)) & 0x33333333UL;
392 encoded = (encoded | (encoded >> 2)) & 0x0F0F0F0FUL;
393 encoded = (encoded | (encoded >> 4)) & 0x00FF00FFUL;
394 return static_cast<TDecoded>(encoded | (encoded >> 8U));
395 }
396
397#if ETL_USING_64BIT_TYPES
398 //*************************************************************************
402 //*************************************************************************
403 template <typename TEncoded>
404 static
405 ETL_CONSTEXPR14 typename etl::enable_if< etl::is_same<TEncoded, uint64_t>::value, typename private_manchester::decoded<TEncoded>::type>::type
406 decode(TEncoded encoded)
407 {
408 typedef typename private_manchester::decoded<TEncoded>::type TDecoded;
409
410 encoded = (encoded ^ (0xAAAAAAAAAAAAAAAAULL ^ TManchesterType::inversion_mask)) & 0x5555555555555555ULL;
411 encoded = (encoded | (encoded >> 1)) & 0x3333333333333333ULL;
412 encoded = (encoded | (encoded >> 2)) & 0x0F0F0F0F0F0F0F0FULL;
413 encoded = (encoded | (encoded >> 4)) & 0x00FF00FF00FF00FFULL;
414 encoded = (encoded | (encoded >> 8)) & 0x0000FFFF0000FFFFULL;
415 return static_cast<TDecoded>(encoded | (encoded >> 16U));
416 }
417#endif
418
419 //*************************************************************************
424 //*************************************************************************
425 template <typename TChunk = typename private_manchester::encoded<uint_least8_t>::type>
426 static ETL_CONSTEXPR14 void decode(etl::span<const uint_least8_t> encoded, etl::span<uint_least8_t> decoded)
427 {
428 typedef typename private_manchester::decoded<TChunk>::type TDecoded;
429 typedef TChunk TEncoded;
430
431 ETL_ASSERT(decoded.size() * 2 >= encoded.size(), ETL_ERROR(manchester_invalid_size));
432 ETL_ASSERT(encoded.size() % sizeof(TChunk) == 0, ETL_ERROR(manchester_invalid_size));
433
434 size_t dest_index = 0;
435 size_t source_index = 0;
436 for (size_t i = 0; i < encoded.size() / sizeof(TEncoded); ++i)
437 {
438 const TEncoded encoded_value = private_manchester::read_little_endian<TEncoded>(encoded, source_index);
439 const TDecoded decoded_value = decode(encoded_value);
440 private_manchester::write_little_endian<TDecoded>(decoded, dest_index, decoded_value);
441
442 source_index += sizeof(TEncoded);
443 dest_index += sizeof(TDecoded);
444 }
445 }
446
447 //*************************************************************************
448 // Validation functions
449 //*************************************************************************
450
451 //*************************************************************************
455 //*************************************************************************
456 template <typename TChunk>
457 ETL_NODISCARD
458 static ETL_CONSTEXPR14 typename etl::enable_if<private_manchester::is_decodable<TChunk>::value, bool>::type is_valid(TChunk encoded)
459 {
460 const TChunk mask = static_cast<TChunk>(0x5555555555555555ULL);
461 return (((encoded ^ (encoded >> 1)) & mask) == mask);
462 }
463
464 //*************************************************************************
468 //*************************************************************************
469 ETL_NODISCARD
470 static ETL_CONSTEXPR14 bool is_valid(etl::span<const uint_least8_t> encoded)
471 {
472 ETL_ASSERT(encoded.size() % sizeof(uint16_t) == 0, ETL_ERROR(manchester_invalid_size));
473
474 for (size_t i = 0; i < encoded.size(); i += sizeof(uint16_t))
475 {
476 const uint16_t chunk = private_manchester::read_little_endian<uint16_t>(encoded, i);
477
478 if (!is_valid<uint16_t>(chunk))
479 {
480 return false;
481 }
482 }
483
484 return true;
485 }
486 };
487
488 //***************************************************************************
491 //***************************************************************************
493
494 //***************************************************************************
497 //***************************************************************************
499
500} // namespace etl
501
502#endif
Exception for Manchester.
Definition manchester.h:213
Invalid size exception for Manchester.
Definition manchester.h:226
Definition limits.h:1715
Span - Fixed Extent.
Definition span.h:208
ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT
Returns the size of the span.
Definition span.h:564
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition exception.h:59
static ETL_CONSTEXPR14 etl::enable_if< etl::is_same< TDecoded, uint32_t >::value, typenameprivate_manchester::encoded< TDecoded >::type >::type encode(TDecoded decoded)
Definition manchester.h:309
static ETL_CONSTEXPR14 etl::enable_if< etl::is_same< TEncoded, uint64_t >::value, typenameprivate_manchester::decoded< TEncoded >::type >::type decode(TEncoded encoded)
Definition manchester.h:406
static ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if< private_manchester::is_decodable< TChunk >::value, bool >::type is_valid(TChunk encoded)
Definition manchester.h:458
static ETL_CONSTEXPR14 void encode(etl::span< const uint_least8_t > decoded, etl::span< uint_least8_t > encoded)
Definition manchester.h:332
static ETL_CONSTEXPR14 etl::enable_if< etl::is_same< TEncoded, uint32_t >::value, typenameprivate_manchester::decoded< TEncoded >::type >::type decode(TEncoded encoded)
Definition manchester.h:386
static ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid(etl::span< const uint_least8_t > encoded)
Definition manchester.h:470
static ETL_CONSTEXPR14 etl::enable_if< etl::is_same< TDecoded, uint16_t >::value, typenameprivate_manchester::encoded< TDecoded >::type >::type encode(TDecoded decoded)
Definition manchester.h:286
static ETL_CONSTEXPR14 void decode(etl::span< const uint_least8_t > encoded, etl::span< uint_least8_t > decoded)
Definition manchester.h:426
manchester_base< private_manchester::manchester_type_normal > manchester
Definition manchester.h:492
manchester_base< private_manchester::manchester_type_inverted > manchester_inverted
Definition manchester.h:498
Definition manchester.h:242
bitset_ext
Definition absolute.h:40
Definition manchester.h:124
Definition manchester.h:90
Definition manchester.h:70
Definition manchester.h:52
Inverted Manchester encoding type.
Definition manchester.h:166
Normal Manchester encoding type (no inversion).
Definition manchester.h:154