diff --git a/openrtx/include/protocols/M17/M17ConvolutionalEncoder.h b/openrtx/include/protocols/M17/M17ConvolutionalEncoder.h new file mode 100644 index 00000000..7985c8e8 --- /dev/null +++ b/openrtx/include/protocols/M17/M17ConvolutionalEncoder.h @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * * + * Adapted from original code written by Rob Riggs, Mobilinkd LLC * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#ifndef M17CONVOLUTIONALENCODER_H +#define M17CONVOLUTIONALENCODER_H + +#ifndef __cplusplus +#error This header is C++ only! +#endif + +#include +#include + +/** + * Convolutional encoder tailored on M17 protocol specifications, requiring a + * coder rate R = 1/2, a constraint length K = 5 and polynomials G1 = 0x19 and + * G2 = 0x17. + */ +class M17ConvolutionalEncoder +{ +public: + + /** + * Constructor. + */ + M17ConvolutionalEncoder(){ } + + /** + * Encode a given block of data using the M17 convolutional encoding scheme. + * Given the coder rate of 1/2, calling code must ensure that the destination + * buffer for the convolved data has twice the size of the original data block. + * + * \param data: pointer to source data block. + * \param convolved: pointer to a destination buffer for the convolved data. + * \param len: length of the source data block. + */ + void encode(const void *data, void *convolved, const size_t len) + { + const uint8_t *src = reinterpret_cast< const uint8_t * >(data); + uint16_t *dest = reinterpret_cast< uint16_t * >(convolved); + + for(size_t i = 0; i < len; i++) + { + dest[i] = convolveByte(src[i]); + } + } + + /** + * Flush the convolutional encoder, returning the remaining encoded data. + * + * \return the convolution encoding of the remaining content of the encoder + * memory. + */ + uint16_t flush() + { + return convolveByte(0x00); + } + + /** + * Reset the convolutional encoder memory to zero. + */ + void reset() + { + memory = 0; + } + +private: + + /** + * Compute the convolutional encoding of a byte, using the M17 encoding + * scheme. + * + * \param value: byte to be convolved. + * \return result of the convolutional encoding process. + */ + uint16_t convolveByte(uint8_t value) + { + uint16_t result = 0; + + for(uint8_t i = 0; i < 8; i++) + { + memory = (memory << 1) | ((value & 0x80) >> 7); + memory &= 0x1F; + result = (result << 1) | (__builtin_popcount(memory & 0x19) & 0x01); + result = (result << 1) | (__builtin_popcount(memory & 0x17) & 0x01); + value <<= 1; + } + + return __builtin_bswap16(result); + } + + uint8_t memory = 0; ///< Convolutional encoder memory. +}; + +#endif /* M17CONVOLUTIONALENCODER_H */