From e91611f45211461d1912380eec0a8c7831448776 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Fri, 30 Nov 2018 15:07:47 +0200 Subject: [PATCH] Implement Golay (24, 12, 8) encoder/decoder --- include/satnogs/CMakeLists.txt | 3 +- include/satnogs/golay24.h | 66 +++++++++++++ lib/CMakeLists.txt | 3 +- lib/golay24.cc | 168 +++++++++++++++++++++++++++++++++ 4 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 include/satnogs/golay24.h create mode 100644 lib/golay24.cc diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index a1ee1cb..7af04b4 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -74,5 +74,6 @@ install(FILES lrpt_sync.h lrpt_decoder.h frame_acquisition.h - shift_reg.h DESTINATION include/satnogs + shift_reg.h + golay24.h DESTINATION include/satnogs ) \ No newline at end of file diff --git a/include/satnogs/golay24.h b/include/satnogs/golay24.h new file mode 100644 index 0000000..99764a1 --- /dev/null +++ b/include/satnogs/golay24.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, 2017, 2018 + * Libre Space Foundation + * + * 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 INCLUDED_SATNOGS_GOLAY24_H +#define INCLUDED_SATNOGS_GOLAY24_H + +#include + +#include +#include + +namespace gr +{ +namespace satnogs +{ + +/*! + * \brief A binary Golay (24,12,8) encoder and decoder. + * + * A binary Golay (24,12,8) encoder and decoder. The implementation uses LUT + * based on the process described in the book: + * + * Morelos-Zaragoza, Robert H. The art of error correcting coding. + * John Wiley & Sons, 2006. + * + */ +class SATNOGS_API golay24 +{ +public: + golay24 (); + ~golay24 (); + + uint32_t + encode12(uint16_t in); + + bool + decode24(uint16_t *out, uint32_t in); +private: + std::vector d_H; + std::vector d_X; + +}; + +} // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_GOLAY24_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 3a574a3..f310ccf 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -73,7 +73,8 @@ list(APPEND satnogs_sources convolutional_deinterleaver.cc lrpt_decoder_impl.cc frame_acquisition_impl.cc - shift_reg.cc) + shift_reg.cc + golay24.cc) if(${INCLUDE_DEBUG_BLOCKS}) list(APPEND satnogs_sources ${satnogs_debug_sources}) diff --git a/lib/golay24.cc b/lib/golay24.cc new file mode 100644 index 0000000..1d6f2a8 --- /dev/null +++ b/lib/golay24.cc @@ -0,0 +1,168 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, 2017, 2018 + * Libre Space Foundation + * + * 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 . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +namespace gr +{ +namespace satnogs +{ + +golay24::golay24 () +{ + + d_H = { 0x7ff, 0xee2, 0xdc5, 0xb8b, 0xf16, 0xe2d, 0xc5b, 0x8b7, 0x96e, 0xadc, + 0xdb8, 0xb71 }; + d_X = {0x800, 0x400, 0x200, 0x100, 0x080, 0x040, 0x020, 0x010, 0x008, 0x004, + 0x002, 0x001}; +} + +golay24::~golay24 () +{ +} + +/** + * Encodes a 12-bit message + * @param in the input 12-bit message. The message should be placed at the + * 12 LS bits + * @return the coded 24-bit message. The message is placed at the 24 LS bits + */ +uint32_t +golay24::encode12 (uint16_t in) +{ + uint32_t c[2] = + { 0x0, 0x0 }; + c[0] = in & 0xFFF; + for (size_t i = 0; i < 12; i++) { + uint32_t tmp = 0; + for (size_t j = 0; j < 12; j++) { + tmp ^= (((c[0] & d_H[i]) >> j) & 0x01); + } + c[1] = (c[1] << 1) ^ tmp; + } + return ((c[0] & 0xFFF) << 12) | (c[1] & 0xFFF); +} + +static inline uint32_t +ham_dist(uint32_t x) +{ + return bit_count(x & 0xFFF); +} + +/** + * Decodes a single Golay (24, 12, 8) codeword + * + * @param out the 12-bit decoded message. The message is placed at the 12 LS bits + * @param in the coded 24 bit code word. The message should be placed at the + * 24 LS bits + * @return true if the decoding was successful, false in case the error correction + * could not be performed + */ +bool +golay24::decode24(uint16_t *out, const uint32_t in) +{ + uint32_t e[2] = {0x0, 0x0}; + uint32_t r[2] = {0x0, 0x0}; + uint32_t c[2] = {0x0, 0x0}; + uint32_t syndrome = 0x0; + bool found = false; + uint32_t col = 0; + uint32_t q = 0; + + r[0] = (in >> 12) & 0xFFF; + r[1] = in & 0xFFF; + + for(size_t j = 0; j < 12; j++) { + uint32_t tmp = 0x0; + for(size_t i = 0; i < 12; i++) { + tmp ^= (((d_X[j] & r[0]) >> i) & 0x1); + } + + for(size_t i = 0; i < 12; i++) { + tmp ^= (((d_H[j] & r[1]) >> i) & 0x1); + } + syndrome = (syndrome << 1) ^ tmp; + } + + if(ham_dist(syndrome) <= 3) { + e[0] = syndrome; + e[1] = 0x0; + } + else{ + do { + if (ham_dist (syndrome ^ d_H[col]) <= 2) { + e[0] = syndrome ^ d_H[col]; + e[1] = d_X[col]; + found = 1; + } + col++; + } + while ((col < 12) && !found); + + if ((col == 12) && !found) { + for (size_t j = 0; j < 12; j++) { + uint32_t tmp = 0x0; + for (size_t i = 0; i < 12; i++) { + tmp ^= (((d_H[j] & syndrome) >> i) & 0x1); + } + q = (q << 1) ^ tmp; + } + } + + if (ham_dist (q) <= 3) { + e[0] = 0; + e[1] = q; + } + else { + col = 0; + found = 0; + do { + if (ham_dist (q ^ d_H[col]) <= 2) { + e[0] = d_X[col]; + e[1] = q ^ d_H[col]; + found = 1; + } + col++; + } + while ((col < 12) && !found); + + if (col == 12 && !found) { + return false; + } + } + } + c[0] = r[0] ^ e[0]; + c[1] = r[1] ^ e[1]; + /* Return the message part only, not the parity */ + *out = c[0]; + return true; +} + +} /* namespace satnogs */ +} /* namespace gr */ +