/////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Edouard Griffiths, F4EXB. // // // // 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 as version 3 of the License, or // // // // 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 V3 for more details. // // // // You should have received a copy of the GNU General Public License // // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// #include "dsd.h" unsigned char Hamming_7_4_m_corr[8]; //!< single bit error correction by syndrome index //!< Generator matrix of bits const unsigned char Hamming_7_4_m_G[7*4] = { 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, }; //!< Parity check matrix of bits const unsigned char Hamming_7_4_m_H[7*3] = { 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 // 0 1 2 3 <- correctable bit positions }; // ======================================================================================== unsigned char Hamming_12_8_m_corr[16]; //!< single bit error correction by syndrome index //!< Generator matrix of bits const unsigned char Hamming_12_8_m_G[12*8] = { 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, }; //!< Parity check matrix of bits const unsigned char Hamming_12_8_m_H[12*4] = { 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1 // 0 1 2 3 4 5 6 7 <- correctable bit positions }; // ======================================================================================== unsigned char Hamming_13_9_m_corr[16]; //!< single bit error correction by syndrome index //!< Generator matrix of bits const unsigned char Hamming_13_9_m_G[13*9] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1 }; //!< Parity check matrix of bits const unsigned char Hamming_13_9_m_H[13*4] = { 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, // 0 1 2 3 4 5 6 7 8 <- correctable bit positions }; // ======================================================================================== unsigned char Hamming_15_11_m_corr[16]; //!< single bit error correction by syndrome index //!< Generator matrix of bits const unsigned char Hamming_15_11_m_G[15*11] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, }; //!< Parity check matrix of bits const unsigned char Hamming_15_11_m_H[15*4] = { 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, // 0 1 2 3 4 5 6 7 8 9 10 <- correctable bit positions }; // ======================================================================================== unsigned char Hamming_16_11_4_m_corr[32]; //!< single bit error correction by syndrome index //!< Generator matrix of bits const unsigned char Hamming_16_11_4_m_G[16*11] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1 }; //!< Parity check matrix of bits const unsigned char Hamming_16_11_4_m_H[16*5] = { 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1 }; // ======================================================================================== unsigned char Golay_20_8_m_corr[4096][3]; //!< up to 3 bit error correction by syndrome index //!< Generator matrix of bits const unsigned char Golay_20_8_m_G[20*8] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, }; //!< Parity check matrix of bits const unsigned char Golay_20_8_m_H[20*12] = { 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, }; // ======================================================================================== unsigned char Golay_23_12_m_corr[2048][3]; //!< up to 3 bit error correction by syndrome index //!< Generator matrix of bits const unsigned char Golay_23_12_m_G[23*12] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, }; //!< Parity check matrix of bits const unsigned char Golay_23_12_m_H[23*11] = { 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, }; // ======================================================================================== unsigned char Golay_24_12_m_corr[4096][3]; //!< up to 3 bit error correction by syndrome index //!< Generator matrix of bits const unsigned char Golay_24_12_m_G[24*12] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, }; //!< Parity check matrix of bits const unsigned char Golay_24_12_m_H[24*12] = { 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, }; // ======================================================================================== unsigned char QR_16_7_6_m_corr[512][2]; //!< up to 2 bit error correction by syndrome index //!< Generator matrix of bits const unsigned char QR_16_7_6_m_G[16*7] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, }; //!< Parity check matrix of bits const unsigned char QR_16_7_6_m_H[16*9] = { 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, }; // ======================================================================================== void Hamming_7_4_init() { // correctable bit positions given syndrome bits as index (see above) memset(Hamming_7_4_m_corr, 0xFF, 8); // initialize with all invalid positions Hamming_7_4_m_corr[0b101] = 0; Hamming_7_4_m_corr[0b111] = 1; Hamming_7_4_m_corr[0b110] = 2; Hamming_7_4_m_corr[0b011] = 3; Hamming_7_4_m_corr[0b100] = 4; Hamming_7_4_m_corr[0b010] = 5; Hamming_7_4_m_corr[0b001] = 6; } // Not very efficient but encode is used for unit testing only void Hamming_7_4_encode(unsigned char *origBits, unsigned char *encodedBits) { int i = 0, j = 0; memset(encodedBits, 0, 7); for (i = 0; i < 4; i++) { for (j = 0; j < 7; j++) { encodedBits[j] += origBits[i] * Hamming_7_4_m_G[7*i + j]; } } for (i = 0; i < 7; i++) { encodedBits[i] %= 2; } } bool Hamming_7_4_decode(unsigned char *rxBits) // corrects in place { unsigned int syndromeI = 0; // syndrome index int is = 0; for (is = 0; is < 3; is++) { syndromeI += (((rxBits[0] * Hamming_7_4_m_H[7*is + 0]) + (rxBits[1] * Hamming_7_4_m_H[7*is + 1]) + (rxBits[2] * Hamming_7_4_m_H[7*is + 2]) + (rxBits[3] * Hamming_7_4_m_H[7*is + 3]) + (rxBits[4] * Hamming_7_4_m_H[7*is + 4]) + (rxBits[5] * Hamming_7_4_m_H[7*is + 5]) + (rxBits[6] * Hamming_7_4_m_H[7*is + 6])) % 2) << (2-is); } if (syndromeI > 0) { if (Hamming_7_4_m_corr[syndromeI] == 0xFF) { return false; } else { rxBits[Hamming_7_4_m_corr[syndromeI]] ^= 1; // flip bit } } return true; } // ======================================================================================== void Hamming_12_8_init() { // correctable bit positions given syndrome bits as index (see above) memset(Hamming_12_8_m_corr, 0xFF, 16); // initialize with all invalid positions Hamming_12_8_m_corr[0b1110] = 0; Hamming_12_8_m_corr[0b0111] = 1; Hamming_12_8_m_corr[0b1010] = 2; Hamming_12_8_m_corr[0b0101] = 3; Hamming_12_8_m_corr[0b1011] = 4; Hamming_12_8_m_corr[0b1100] = 5; Hamming_12_8_m_corr[0b0110] = 6; Hamming_12_8_m_corr[0b0011] = 7; Hamming_12_8_m_corr[0b1000] = 8; Hamming_12_8_m_corr[0b0100] = 9; Hamming_12_8_m_corr[0b0010] = 10; Hamming_12_8_m_corr[0b0001] = 11; } // Not very efficient but encode is used for unit testing only void Hamming_12_8_encode(unsigned char *origBits, unsigned char *encodedBits) { int i = 0, j = 0; memset(encodedBits, 0, 12); for (i = 0; i < 8; i++) { for (j = 0; j < 12; j++) { encodedBits[j] += origBits[i] * Hamming_12_8_m_G[12*i + j]; } } for (i = 0; i < 12; i++) { encodedBits[i] %= 2; } } bool Hamming_12_8_decode(unsigned char *rxBits, unsigned char *decodedBits, int nbCodewords) { bool correctable = true; int ic = 0; int is = 0; int syndromeI = 0; // syndrome index for (ic = 0; ic < nbCodewords; ic++) { // calculate syndrome syndromeI = 0; // syndrome index for (is = 0; is < 4; is++) { syndromeI += (((rxBits[12*ic + 0] * Hamming_12_8_m_H[12*is + 0]) + (rxBits[12*ic + 1] * Hamming_12_8_m_H[12*is + 1]) + (rxBits[12*ic + 2] * Hamming_12_8_m_H[12*is + 2]) + (rxBits[12*ic + 3] * Hamming_12_8_m_H[12*is + 3]) + (rxBits[12*ic + 4] * Hamming_12_8_m_H[12*is + 4]) + (rxBits[12*ic + 5] * Hamming_12_8_m_H[12*is + 5]) + (rxBits[12*ic + 6] * Hamming_12_8_m_H[12*is + 6]) + (rxBits[12*ic + 7] * Hamming_12_8_m_H[12*is + 7]) + (rxBits[12*ic + 8] * Hamming_12_8_m_H[12*is + 8]) + (rxBits[12*ic + 9] * Hamming_12_8_m_H[12*is + 9]) + (rxBits[12*ic + 10] * Hamming_12_8_m_H[12*is + 10]) + (rxBits[12*ic + 11] * Hamming_12_8_m_H[12*is + 11])) % 2) << (3-is); } // correct bit if (syndromeI > 0) // single bit error correction { if (Hamming_12_8_m_corr[syndromeI] == 0xFF) // uncorrectable error { correctable = false; } else { rxBits[Hamming_12_8_m_corr[syndromeI]] ^= 1; // flip bit } } // move information bits memcpy(&decodedBits[8*ic], &rxBits[12*ic], 8); } return correctable; } // ======================================================================================== void Hamming_13_9_init() { // correctable bit positions given syndrome bits as index (see above) memset(Hamming_13_9_m_corr, 0xFF, 16); // initialize with all invalid positions Hamming_13_9_m_corr[0b1111] = 0; Hamming_13_9_m_corr[0b1110] = 1; Hamming_13_9_m_corr[0b0111] = 2; Hamming_13_9_m_corr[0b1010] = 3; Hamming_13_9_m_corr[0b0101] = 4; Hamming_13_9_m_corr[0b1011] = 5; Hamming_13_9_m_corr[0b1100] = 6; Hamming_13_9_m_corr[0b0110] = 7; Hamming_13_9_m_corr[0b0011] = 8; Hamming_13_9_m_corr[0b1000] = 9; Hamming_13_9_m_corr[0b0100] = 10; Hamming_13_9_m_corr[0b0010] = 11; Hamming_13_9_m_corr[0b0001] = 12; } // Not very efficient but encode is used for unit testing only void Hamming_13_9_encode(unsigned char *origBits, unsigned char *encodedBits) { int i = 0, j = 0; memset(encodedBits, 0, 13); for (i = 0; i < 9; i++) { for (j = 0; j < 13; j++) { encodedBits[j] += origBits[i] * Hamming_13_9_m_G[13*i + j]; } } for (i = 0; i < 13; i++) { encodedBits[i] %= 2; } } bool Hamming_13_9_decode(unsigned char *rxBits, unsigned char *decodedBits, int nbCodewords) { bool correctable = true; int ic = 0, is = 0; int syndromeI = 0; // syndrome index for (ic = 0; ic < nbCodewords; ic++) { // calculate syndrome syndromeI = 0; // syndrome index for (is = 0; is < 4; is++) { syndromeI += (((rxBits[13*ic + 0] * Hamming_13_9_m_H[13*is + 0]) + (rxBits[13*ic + 1] * Hamming_13_9_m_H[13*is + 1]) + (rxBits[13*ic + 2] * Hamming_13_9_m_H[13*is + 2]) + (rxBits[13*ic + 3] * Hamming_13_9_m_H[13*is + 3]) + (rxBits[13*ic + 4] * Hamming_13_9_m_H[13*is + 4]) + (rxBits[13*ic + 5] * Hamming_13_9_m_H[13*is + 5]) + (rxBits[13*ic + 6] * Hamming_13_9_m_H[13*is + 6]) + (rxBits[13*ic + 7] * Hamming_13_9_m_H[13*is + 7]) + (rxBits[13*ic + 8] * Hamming_13_9_m_H[13*is + 8]) + (rxBits[13*ic + 9] * Hamming_13_9_m_H[13*is + 9]) + (rxBits[13*ic + 10] * Hamming_13_9_m_H[13*is + 10]) + (rxBits[13*ic + 11] * Hamming_13_9_m_H[13*is + 11]) + (rxBits[13*ic + 12] * Hamming_13_9_m_H[13*is + 12])) % 2) << (3-is); } // correct bit if (syndromeI > 0) // single bit error correction { if (Hamming_13_9_m_corr[syndromeI] == 0xFF) // uncorrectable error { correctable = false; break; } else { rxBits[Hamming_13_9_m_corr[syndromeI]] ^= 1; // flip bit } } // move information bits if (decodedBits) { memcpy(&decodedBits[9*ic], &rxBits[13*ic], 9); } } return correctable; } // ======================================================================================== void Hamming_15_11_init() { // correctable bit positions given syndrome bits as index (see above) memset(Hamming_15_11_m_corr, 0xFF, 16); // initialize with all invalid positions Hamming_15_11_m_corr[0b1001] = 0; Hamming_15_11_m_corr[0b1101] = 1; Hamming_15_11_m_corr[0b1111] = 2; Hamming_15_11_m_corr[0b1110] = 3; Hamming_15_11_m_corr[0b0111] = 4; Hamming_15_11_m_corr[0b1010] = 5; Hamming_15_11_m_corr[0b0101] = 6; Hamming_15_11_m_corr[0b1011] = 7; Hamming_15_11_m_corr[0b1100] = 8; Hamming_15_11_m_corr[0b0110] = 9; Hamming_15_11_m_corr[0b0011] = 10; Hamming_15_11_m_corr[0b1000] = 11; Hamming_15_11_m_corr[0b0100] = 12; Hamming_15_11_m_corr[0b0010] = 13; Hamming_15_11_m_corr[0b0001] = 14; } // Not very efficient but encode is used for unit testing only void Hamming_15_11_encode(unsigned char *origBits, unsigned char *encodedBits) { int i = 0, j = 0; memset(encodedBits, 0, 15); for (i = 0; i < 11; i++) { for (j = 0; j < 15; j++) { encodedBits[j] += origBits[i] * Hamming_15_11_m_G[15*i + j]; } } for (i = 0; i < 15; i++) { encodedBits[i] %= 2; } } bool Hamming_15_11_decode(unsigned char *rxBits, unsigned char *decodedBits, int nbCodewords) { bool correctable = true; int ic = 0, is = 0; int syndromeI = 0; // syndrome index for (ic = 0; ic < nbCodewords; ic++) { // calculate syndrome syndromeI = 0; // syndrome index for (is = 0; is < 4; is++) { syndromeI += (((rxBits[15*ic + 0] * Hamming_15_11_m_H[15*is + 0]) + (rxBits[15*ic + 1] * Hamming_15_11_m_H[15*is + 1]) + (rxBits[15*ic + 2] * Hamming_15_11_m_H[15*is + 2]) + (rxBits[15*ic + 3] * Hamming_15_11_m_H[15*is + 3]) + (rxBits[15*ic + 4] * Hamming_15_11_m_H[15*is + 4]) + (rxBits[15*ic + 5] * Hamming_15_11_m_H[15*is + 5]) + (rxBits[15*ic + 6] * Hamming_15_11_m_H[15*is + 6]) + (rxBits[15*ic + 7] * Hamming_15_11_m_H[15*is + 7]) + (rxBits[15*ic + 8] * Hamming_15_11_m_H[15*is + 8]) + (rxBits[15*ic + 9] * Hamming_15_11_m_H[15*is + 9]) + (rxBits[15*ic + 10] * Hamming_15_11_m_H[15*is + 10]) + (rxBits[15*ic + 11] * Hamming_15_11_m_H[15*is + 11]) + (rxBits[15*ic + 12] * Hamming_15_11_m_H[15*is + 12]) + (rxBits[15*ic + 13] * Hamming_15_11_m_H[15*is + 13]) + (rxBits[15*ic + 14] * Hamming_15_11_m_H[15*is + 14])) % 2) << (3-is); } // correct bit if (syndromeI > 0) // single bit error correction { if (Hamming_15_11_m_corr[syndromeI] == 0xFF) // uncorrectable error { correctable = false; break; } else { rxBits[Hamming_15_11_m_corr[syndromeI]] ^= 1; // flip bit } } // move information bits if (decodedBits) { memcpy(&decodedBits[11*ic], &rxBits[15*ic], 11); } } return correctable; } // ======================================================================================== void Hamming_16_11_4_init() { // correctable bit positions given syndrome bits as index (see above) memset(Hamming_16_11_4_m_corr, 0xFF, 32); // initialize with all invalid positions Hamming_16_11_4_m_corr[0b10011] = 0; Hamming_16_11_4_m_corr[0b11010] = 1; Hamming_16_11_4_m_corr[0b11111] = 2; Hamming_16_11_4_m_corr[0b11100] = 3; Hamming_16_11_4_m_corr[0b01110] = 4; Hamming_16_11_4_m_corr[0b10101] = 5; Hamming_16_11_4_m_corr[0b01011] = 6; Hamming_16_11_4_m_corr[0b10110] = 7; Hamming_16_11_4_m_corr[0b11001] = 8; Hamming_16_11_4_m_corr[0b01101] = 9; Hamming_16_11_4_m_corr[0b00111] = 10; Hamming_16_11_4_m_corr[0b10000] = 11; Hamming_16_11_4_m_corr[0b01000] = 12; Hamming_16_11_4_m_corr[0b00100] = 13; Hamming_16_11_4_m_corr[0b00010] = 14; Hamming_16_11_4_m_corr[0b00001] = 15; } // Not very efficient but encode is used for unit testing only void Hamming_16_11_4_encode(unsigned char *origBits, unsigned char *encodedBits) { int i = 0, j = 0; memset(encodedBits, 0, 16); for (i = 0; i < 11; i++) { for (j = 0; j < 16; j++) { encodedBits[j] += origBits[i] * Hamming_16_11_4_m_G[16*i + j]; } } for (i = 0; i < 16; i++) { encodedBits[i] %= 2; } } bool Hamming_16_11_4_decode(unsigned char *rxBits, unsigned char *decodedBits, int nbCodewords) { bool correctable = true; int ic = 0, is = 0; int syndromeI = 0; // syndrome index for (ic = 0; ic < nbCodewords; ic++) { // calculate syndrome syndromeI = 0; // syndrome index for (is = 0; is < 5; is++) { syndromeI += (((rxBits[16*ic + 0] * Hamming_16_11_4_m_H[16*is + 0]) + (rxBits[16*ic + 1] * Hamming_16_11_4_m_H[16*is + 1]) + (rxBits[16*ic + 2] * Hamming_16_11_4_m_H[16*is + 2]) + (rxBits[16*ic + 3] * Hamming_16_11_4_m_H[16*is + 3]) + (rxBits[16*ic + 4] * Hamming_16_11_4_m_H[16*is + 4]) + (rxBits[16*ic + 5] * Hamming_16_11_4_m_H[16*is + 5]) + (rxBits[16*ic + 6] * Hamming_16_11_4_m_H[16*is + 6]) + (rxBits[16*ic + 7] * Hamming_16_11_4_m_H[16*is + 7]) + (rxBits[16*ic + 8] * Hamming_16_11_4_m_H[16*is + 8]) + (rxBits[16*ic + 9] * Hamming_16_11_4_m_H[16*is + 9]) + (rxBits[16*ic + 10] * Hamming_16_11_4_m_H[16*is + 10]) + (rxBits[16*ic + 11] * Hamming_16_11_4_m_H[16*is + 11]) + (rxBits[16*ic + 12] * Hamming_16_11_4_m_H[16*is + 12]) + (rxBits[16*ic + 13] * Hamming_16_11_4_m_H[16*is + 13]) + (rxBits[16*ic + 14] * Hamming_16_11_4_m_H[16*is + 14]) + (rxBits[16*ic + 15] * Hamming_16_11_4_m_H[16*is + 15])) % 2) << (4-is); } // correct bit if (syndromeI > 0) // single bit error correction { if (Hamming_16_11_4_m_corr[syndromeI] == 0xFF) // uncorrectable error { correctable = false; break; } else { rxBits[Hamming_16_11_4_m_corr[syndromeI]] ^= 1; // flip bit } } // move information bits if (decodedBits) { memcpy(&decodedBits[11*ic], &rxBits[16*ic], 11); } } return correctable; } // ======================================================================================== void Golay_20_8_init() { int i1 = 0, i2 = 0, i3 = 0, ir = 0, ip = 0; int syndromeI = 0, syndromeIP = 0; int ip1 = 0, ip2 = 0, ip3 = 0; int syndromeIP1 = 0, syndromeIP2 = 0, syndromeIP3 = 0; memset(Golay_20_8_m_corr, 0xFF, 3*4096); for (i1 = 0; i1 < 8; i1++) { for (i2 = i1+1; i2 < 8; i2++) { for (i3 = i2+1; i3 < 8; i3++) { // 3 bit patterns syndromeI = 0; for (ir = 0; ir < 12; ir++) { syndromeI += ((Golay_20_8_m_H[20*ir + i1] + Golay_20_8_m_H[20*ir + i2] + Golay_20_8_m_H[20*ir + i3]) % 2) << (11-ir); } Golay_20_8_m_corr[syndromeI][0] = i1; Golay_20_8_m_corr[syndromeI][1] = i2; Golay_20_8_m_corr[syndromeI][2] = i3; } // 2 bit patterns syndromeI = 0; for (ir = 0; ir < 12; ir++) { syndromeI += ((Golay_20_8_m_H[20*ir + i1] + Golay_20_8_m_H[20*ir + i2]) % 2) << (11-ir); } Golay_20_8_m_corr[syndromeI][0] = i1; Golay_20_8_m_corr[syndromeI][1] = i2; // 1 possible bit flip left in the parity part for (ip = 0; ip < 12; ip++) { syndromeIP = syndromeI ^ (1 << (11-ip)); Golay_20_8_m_corr[syndromeIP][0] = i1; Golay_20_8_m_corr[syndromeIP][1] = i2; Golay_20_8_m_corr[syndromeIP][2] = 12 + ip; } } // single bit patterns syndromeI = 0; for (ir = 0; ir < 12; ir++) { syndromeI += Golay_20_8_m_H[20*ir + i1] << (11-ir); } Golay_20_8_m_corr[syndromeI][0] = i1; for (ip1 = 0; ip1 < 12; ip1++) // 1 more bit flip in parity { syndromeIP1 = syndromeI ^ (1 << (11-ip1)); Golay_20_8_m_corr[syndromeIP1][0] = i1; Golay_20_8_m_corr[syndromeIP1][1] = 12 + ip1; for (ip2 = ip1+1; ip2 < 12; ip2++) // 1 more bit flip in parity { syndromeIP2 = syndromeIP1 ^ (1 << (11-ip2)); Golay_20_8_m_corr[syndromeIP2][0] = i1; Golay_20_8_m_corr[syndromeIP2][1] = 12 + ip1; Golay_20_8_m_corr[syndromeIP2][2] = 12 + ip2; } } } // no bit patterns (in message) -> all in parity for (ip1 = 0; ip1 < 12; ip1++) // 1 bit flip in parity { syndromeIP1 = (1 << (11-ip1)); Golay_20_8_m_corr[syndromeIP1][0] = 12 + ip1; for (ip2 = ip1+1; ip2 < 12; ip2++) // 1 more bit flip in parity { syndromeIP2 = syndromeIP1 ^ (1 << (11-ip2)); Golay_20_8_m_corr[syndromeIP2][0] = 12 + ip1; Golay_20_8_m_corr[syndromeIP2][1] = 12 + ip2; for (ip3 = ip2+1; ip3 < 12; ip3++) // 1 more bit flip in parity { syndromeIP3 = syndromeIP2 ^ (1 << (11-ip3)); Golay_20_8_m_corr[syndromeIP3][0] = 12 + ip1; Golay_20_8_m_corr[syndromeIP3][1] = 12 + ip2; Golay_20_8_m_corr[syndromeIP3][2] = 12 + ip3; } } } } // Not very efficient but encode is used for unit testing only void Golay_20_8_encode(unsigned char *origBits, unsigned char *encodedBits) { int i = 0, j = 0; memset(encodedBits, 0, 20); for (i = 0; i < 8; i++) { for (j = 0; j < 20; j++) { encodedBits[j] += origBits[i] * Golay_20_8_m_G[20*i + j]; } } for (i = 0; i < 20; i++) { encodedBits[i] %= 2; } } bool Golay_20_8_decode(unsigned char *rxBits) { unsigned int syndromeI = 0; // syndrome index int is = 0; int i = 0; for (is = 0; is < 12; is++) { syndromeI += (((rxBits[0] * Golay_20_8_m_H[20*is + 0]) + (rxBits[1] * Golay_20_8_m_H[20*is + 1]) + (rxBits[2] * Golay_20_8_m_H[20*is + 2]) + (rxBits[3] * Golay_20_8_m_H[20*is + 3]) + (rxBits[4] * Golay_20_8_m_H[20*is + 4]) + (rxBits[5] * Golay_20_8_m_H[20*is + 5]) + (rxBits[6] * Golay_20_8_m_H[20*is + 6]) + (rxBits[7] * Golay_20_8_m_H[20*is + 7]) + (rxBits[8] * Golay_20_8_m_H[20*is + 8]) + (rxBits[9] * Golay_20_8_m_H[20*is + 9]) + (rxBits[10] * Golay_20_8_m_H[20*is + 10]) + (rxBits[11] * Golay_20_8_m_H[20*is + 11]) + (rxBits[12] * Golay_20_8_m_H[20*is + 12]) + (rxBits[13] * Golay_20_8_m_H[20*is + 13]) + (rxBits[14] * Golay_20_8_m_H[20*is + 14]) + (rxBits[15] * Golay_20_8_m_H[20*is + 15]) + (rxBits[16] * Golay_20_8_m_H[20*is + 16]) + (rxBits[17] * Golay_20_8_m_H[20*is + 17]) + (rxBits[18] * Golay_20_8_m_H[20*is + 18]) + (rxBits[19] * Golay_20_8_m_H[20*is + 19])) % 2) << (11-is); } if (syndromeI > 0) { i = 0; for (; i < 3; i++) { if (Golay_20_8_m_corr[syndromeI][i] == 0xFF) { break; } else { rxBits[Golay_20_8_m_corr[syndromeI][i]] ^= 1; // flip bit } } if (i == 0) { return false; } } return true; } // ======================================================================================== void Golay_23_12_init() { int i1 = 0, i2 = 0, i3 = 0, ir = 0, ip = 0; int syndromeI = 0, syndromeIP = 0; int ip1 = 0, ip2 = 0, ip3 = 0; int syndromeIP1 = 0, syndromeIP2 = 0, syndromeIP3 = 0; memset(Golay_23_12_m_corr, 0xFF, 3*2048); for (i1 = 0; i1 < 12; i1++) { for (i2 = i1+1; i2 < 12; i2++) { for (i3 = i2+1; i3 < 12; i3++) { // 3 bit patterns syndromeI = 0; for (ir = 0; ir < 11; ir++) { syndromeI += ((Golay_23_12_m_H[23*ir + i1] + Golay_23_12_m_H[23*ir + i2] + Golay_23_12_m_H[23*ir + i3]) % 2) << (10-ir); } Golay_23_12_m_corr[syndromeI][0] = i1; Golay_23_12_m_corr[syndromeI][1] = i2; Golay_23_12_m_corr[syndromeI][2] = i3; } // 2 bit patterns syndromeI = 0; for (ir = 0; ir < 11; ir++) { syndromeI += ((Golay_23_12_m_H[23*ir + i1] + Golay_23_12_m_H[23*ir + i2]) % 2) << (10-ir); } Golay_23_12_m_corr[syndromeI][0] = i1; Golay_23_12_m_corr[syndromeI][1] = i2; // 1 possible bit flip left in the parity part for (ip = 0; ip < 11; ip++) { syndromeIP = syndromeI ^ (1 << (10-ip)); Golay_23_12_m_corr[syndromeIP][0] = i1; Golay_23_12_m_corr[syndromeIP][1] = i2; Golay_23_12_m_corr[syndromeIP][2] = 12 + ip; } } // single bit patterns syndromeI = 0; for (ir = 0; ir < 11; ir++) { syndromeI += Golay_23_12_m_H[23*ir + i1] << (10-ir); } Golay_23_12_m_corr[syndromeI][0] = i1; for (ip1 = 0; ip1 < 11; ip1++) // 1 more bit flip in parity { syndromeIP1 = syndromeI ^ (1 << (10-ip1)); Golay_23_12_m_corr[syndromeIP1][0] = i1; Golay_23_12_m_corr[syndromeIP1][1] = 12 + ip1; for (ip2 = ip1+1; ip2 < 11; ip2++) // 1 more bit flip in parity { syndromeIP2 = syndromeIP1 ^ (1 << (10-ip2)); Golay_23_12_m_corr[syndromeIP2][0] = i1; Golay_23_12_m_corr[syndromeIP2][1] = 12 + ip1; Golay_23_12_m_corr[syndromeIP2][2] = 12 + ip2; } } } // no bit patterns (in message) -> all in parity for (ip1 = 0; ip1 < 11; ip1++) // 1 bit flip in parity { syndromeIP1 = (1 << (10-ip1)); Golay_23_12_m_corr[syndromeIP1][0] = 12 + ip1; for (ip2 = ip1+1; ip2 < 11; ip2++) // 1 more bit flip in parity { syndromeIP2 = syndromeIP1 ^ (1 << (10-ip2)); Golay_23_12_m_corr[syndromeIP2][0] = 12 + ip1; Golay_23_12_m_corr[syndromeIP2][1] = 12 + ip2; for (ip3 = ip2+1; ip3 < 11; ip3++) // 1 more bit flip in parity { syndromeIP3 = syndromeIP2 ^ (1 << (10-ip3)); Golay_23_12_m_corr[syndromeIP3][0] = 12 + ip1; Golay_23_12_m_corr[syndromeIP3][1] = 12 + ip2; Golay_23_12_m_corr[syndromeIP3][2] = 12 + ip3; } } } } // Not very efficient but encode is used for unit testing only void Golay_23_12_encode(unsigned char *origBits, unsigned char *encodedBits) { int i = 0, j = 0; memset(encodedBits, 0, 23); for (i = 0; i < 12; i++) // orig bits { for (j = 0; j < 23; j++) // codeword bits { encodedBits[j] += origBits[i] * Golay_23_12_m_G[23*i + j]; } } for (i = 0; i < 23; i++) { encodedBits[i] %= 2; } } bool Golay_23_12_decode(unsigned char *rxBits) { unsigned int syndromeI = 0; // syndrome index int is = 0; int i = 0; for (is = 0; is < 11; is++) { syndromeI += (((rxBits[0] * Golay_23_12_m_H[23*is + 0]) + (rxBits[1] * Golay_23_12_m_H[23*is + 1]) + (rxBits[2] * Golay_23_12_m_H[23*is + 2]) + (rxBits[3] * Golay_23_12_m_H[23*is + 3]) + (rxBits[4] * Golay_23_12_m_H[23*is + 4]) + (rxBits[5] * Golay_23_12_m_H[23*is + 5]) + (rxBits[6] * Golay_23_12_m_H[23*is + 6]) + (rxBits[7] * Golay_23_12_m_H[23*is + 7]) + (rxBits[8] * Golay_23_12_m_H[23*is + 8]) + (rxBits[9] * Golay_23_12_m_H[23*is + 9]) + (rxBits[10] * Golay_23_12_m_H[23*is + 10]) + (rxBits[11] * Golay_23_12_m_H[23*is + 11]) + (rxBits[12] * Golay_23_12_m_H[23*is + 12]) + (rxBits[13] * Golay_23_12_m_H[23*is + 13]) + (rxBits[14] * Golay_23_12_m_H[23*is + 14]) + (rxBits[15] * Golay_23_12_m_H[23*is + 15]) + (rxBits[16] * Golay_23_12_m_H[23*is + 16]) + (rxBits[17] * Golay_23_12_m_H[23*is + 17]) + (rxBits[18] * Golay_23_12_m_H[23*is + 18]) + (rxBits[19] * Golay_23_12_m_H[23*is + 19]) + (rxBits[20] * Golay_23_12_m_H[23*is + 20]) + (rxBits[21] * Golay_23_12_m_H[23*is + 21]) + (rxBits[22] * Golay_23_12_m_H[23*is + 22])) % 2) << (10-is); } if (syndromeI > 0) { i = 0; for (; i < 3; i++) { if (Golay_23_12_m_corr[syndromeI][i] == 0xFF) { break; } else { rxBits[Golay_23_12_m_corr[syndromeI][i]] ^= 1; // flip bit } } if (i == 0) { return false; } } return true; } // ======================================================================================== void Golay_24_12_init() { int i1 = 0, i2 = 0, i3 = 0, ir = 0, ip = 0; int syndromeI = 0, syndromeIP = 0; int ip1 = 0, ip2 = 0, ip3 = 0; int syndromeIP1 = 0, syndromeIP2 = 0, syndromeIP3 = 0; memset (Golay_24_12_m_corr, 0xFF, 3*4096); for (i1 = 0; i1 < 12; i1++) { for (i2 = i1+1; i2 < 12; i2++) { for (i3 = i2+1; i3 < 12; i3++) { // 3 bit patterns syndromeI = 0; for (ir = 0; ir < 12; ir++) { syndromeI += ((Golay_24_12_m_H[24*ir + i1] + Golay_24_12_m_H[24*ir + i2] + Golay_24_12_m_H[24*ir + i3]) % 2) << (11-ir); } Golay_24_12_m_corr[syndromeI][0] = i1; Golay_24_12_m_corr[syndromeI][1] = i2; Golay_24_12_m_corr[syndromeI][2] = i3; } // 2 bit patterns syndromeI = 0; for (ir = 0; ir < 12; ir++) { syndromeI += ((Golay_24_12_m_H[24*ir + i1] + Golay_24_12_m_H[24*ir + i2]) % 2) << (11-ir); } Golay_24_12_m_corr[syndromeI][0] = i1; Golay_24_12_m_corr[syndromeI][1] = i2; // 1 possible bit flip left in the parity part for (ip = 0; ip < 12; ip++) { syndromeIP = syndromeI ^ (1 << (11-ip)); Golay_24_12_m_corr[syndromeIP][0] = i1; Golay_24_12_m_corr[syndromeIP][1] = i2; Golay_24_12_m_corr[syndromeIP][2] = 12 + ip; } } // single bit patterns syndromeI = 0; for (ir = 0; ir < 12; ir++) { syndromeI += Golay_24_12_m_H[24*ir + i1] << (11-ir); } Golay_24_12_m_corr[syndromeI][0] = i1; for (ip1 = 0; ip1 < 12; ip1++) // 1 more bit flip in parity { syndromeIP1 = syndromeI ^ (1 << (11-ip1)); Golay_24_12_m_corr[syndromeIP1][0] = i1; Golay_24_12_m_corr[syndromeIP1][1] = 12 + ip1; for (ip2 = ip1+1; ip2 < 12; ip2++) // 1 more bit flip in parity { syndromeIP2 = syndromeIP1 ^ (1 << (11-ip2)); Golay_24_12_m_corr[syndromeIP2][0] = i1; Golay_24_12_m_corr[syndromeIP2][1] = 12 + ip1; Golay_24_12_m_corr[syndromeIP2][2] = 12 + ip2; } } } // no bit patterns (in message) -> all in parity for (ip1 = 0; ip1 < 12; ip1++) // 1 bit flip in parity { syndromeIP1 = (1 << (11-ip1)); Golay_24_12_m_corr[syndromeIP1][0] = 12 + ip1; for (ip2 = ip1+1; ip2 < 12; ip2++) // 1 more bit flip in parity { syndromeIP2 = syndromeIP1 ^ (1 << (11-ip2)); Golay_24_12_m_corr[syndromeIP2][0] = 12 + ip1; Golay_24_12_m_corr[syndromeIP2][1] = 12 + ip2; for (ip3 = ip2+1; ip3 < 12; ip3++) // 1 more bit flip in parity { syndromeIP3 = syndromeIP2 ^ (1 << (11-ip3)); Golay_24_12_m_corr[syndromeIP3][0] = 12 + ip1; Golay_24_12_m_corr[syndromeIP3][1] = 12 + ip2; Golay_24_12_m_corr[syndromeIP3][2] = 12 + ip3; } } } } // Not very efficient but encode is used for unit testing only void Golay_24_12_encode(unsigned char *origBits, unsigned char *encodedBits) { int i = 0, j = 0; memset(encodedBits, 0, 24); for (i = 0; i < 12; i++) { for (j = 0; j < 24; j++) { encodedBits[j] += origBits[i] * Golay_24_12_m_G[24*i + j]; } } for (i = 0; i < 24; i++) { encodedBits[i] %= 2; } } bool Golay_24_12_decode(unsigned char *rxBits) { unsigned int syndromeI = 0; // syndrome index int is = 0; int i = 0; for (is = 0; is < 12; is++) { syndromeI += (((rxBits[0] * Golay_24_12_m_H[24*is + 0]) + (rxBits[1] * Golay_24_12_m_H[24*is + 1]) + (rxBits[2] * Golay_24_12_m_H[24*is + 2]) + (rxBits[3] * Golay_24_12_m_H[24*is + 3]) + (rxBits[4] * Golay_24_12_m_H[24*is + 4]) + (rxBits[5] * Golay_24_12_m_H[24*is + 5]) + (rxBits[6] * Golay_24_12_m_H[24*is + 6]) + (rxBits[7] * Golay_24_12_m_H[24*is + 7]) + (rxBits[8] * Golay_24_12_m_H[24*is + 8]) + (rxBits[9] * Golay_24_12_m_H[24*is + 9]) + (rxBits[10] * Golay_24_12_m_H[24*is + 10]) + (rxBits[11] * Golay_24_12_m_H[24*is + 11]) + (rxBits[12] * Golay_24_12_m_H[24*is + 12]) + (rxBits[13] * Golay_24_12_m_H[24*is + 13]) + (rxBits[14] * Golay_24_12_m_H[24*is + 14]) + (rxBits[15] * Golay_24_12_m_H[24*is + 15]) + (rxBits[16] * Golay_24_12_m_H[24*is + 16]) + (rxBits[17] * Golay_24_12_m_H[24*is + 17]) + (rxBits[18] * Golay_24_12_m_H[24*is + 18]) + (rxBits[19] * Golay_24_12_m_H[24*is + 19]) + (rxBits[20] * Golay_24_12_m_H[24*is + 20]) + (rxBits[21] * Golay_24_12_m_H[24*is + 21]) + (rxBits[22] * Golay_24_12_m_H[24*is + 22]) + (rxBits[23] * Golay_24_12_m_H[24*is + 23])) % 2) << (11-is); } if (syndromeI > 0) { i = 0; for (; i < 3; i++) { if (Golay_24_12_m_corr[syndromeI][i] == 0xFF) { break; } else { rxBits[Golay_24_12_m_corr[syndromeI][i]] ^= 1; // flip bit } } if (i == 0) { return false; } } return true; } // ======================================================================================== void QR_16_7_6_init() { int i1 = 0, i2 = 0, ir = 0, ip = 0; int syndromeI = 0, syndromeIP = 0; int ip1 = 0, ip2 = 0; int syndromeIP1 = 0, syndromeIP2 = 0; memset(QR_16_7_6_m_corr, 0xFF, 2*512); for (i1 = 0; i1 < 7; i1++) { for (i2 = i1+1; i2 < 7; i2++) { // 2 bit patterns syndromeI = 0; for (ir = 0; ir < 9; ir++) { syndromeI += ((QR_16_7_6_m_H[16*ir + i1] + QR_16_7_6_m_H[16*ir + i2]) % 2) << (8-ir); } QR_16_7_6_m_corr[syndromeI][0] = i1; QR_16_7_6_m_corr[syndromeI][1] = i2; } // single bit patterns syndromeI = 0; for (ir = 0; ir < 9; ir++) { syndromeI += QR_16_7_6_m_H[16*ir + i1] << (8-ir); } QR_16_7_6_m_corr[syndromeI][0] = i1; // 1 possible bit flip left in the parity part for (ip = 0; ip < 9; ip++) { syndromeIP = syndromeI ^ (1 << (8-ip)); QR_16_7_6_m_corr[syndromeIP][0] = i1; QR_16_7_6_m_corr[syndromeIP][1] = 7 + ip; } } // no bit patterns (in message) -> all in parity for (ip1 = 0; ip1 < 9; ip1++) // 1 bit flip in parity { syndromeIP1 = (1 << (8-ip1)); QR_16_7_6_m_corr[syndromeIP1][0] = 7 + ip1; for (ip2 = ip1+1; ip2 < 9; ip2++) // 1 more bit flip in parity { syndromeIP2 = syndromeIP1 ^ (1 << (8-ip2)); QR_16_7_6_m_corr[syndromeIP2][0] = 7 + ip1; QR_16_7_6_m_corr[syndromeIP2][1] = 7 + ip2; } } } // Not very efficient but encode is used for unit testing only void QR_16_7_6_encode(unsigned char *origBits, unsigned char *encodedBits) { int i = 0, j = 0; memset(encodedBits, 0, 16); for (i = 0; i < 7; i++) { for (j = 0; j < 16; j++) { encodedBits[j] += origBits[i] * QR_16_7_6_m_G[16*i + j]; } } for (i = 0; i < 16; i++) { encodedBits[i] %= 2; } } bool QR_16_7_6_decode(unsigned char *rxBits) { unsigned int syndromeI = 0; // syndrome index int is = 0; int i = 0; for (is = 0; is < 9; is++) { syndromeI += (((rxBits[0] * QR_16_7_6_m_H[16*is + 0]) + (rxBits[1] * QR_16_7_6_m_H[16*is + 1]) + (rxBits[2] * QR_16_7_6_m_H[16*is + 2]) + (rxBits[3] * QR_16_7_6_m_H[16*is + 3]) + (rxBits[4] * QR_16_7_6_m_H[16*is + 4]) + (rxBits[5] * QR_16_7_6_m_H[16*is + 5]) + (rxBits[6] * QR_16_7_6_m_H[16*is + 6]) + (rxBits[7] * QR_16_7_6_m_H[16*is + 7]) + (rxBits[8] * QR_16_7_6_m_H[16*is + 8]) + (rxBits[9] * QR_16_7_6_m_H[16*is + 9]) + (rxBits[10] * QR_16_7_6_m_H[16*is + 10]) + (rxBits[11] * QR_16_7_6_m_H[16*is + 11]) + (rxBits[12] * QR_16_7_6_m_H[16*is + 12]) + (rxBits[13] * QR_16_7_6_m_H[16*is + 13]) + (rxBits[14] * QR_16_7_6_m_H[16*is + 14]) + (rxBits[15] * QR_16_7_6_m_H[16*is + 15])) % 2) << (8-is); } if (syndromeI > 0) { i = 0; for (; i < 2; i++) { if (QR_16_7_6_m_corr[syndromeI][i] == 0xFF) { break; } else { rxBits[QR_16_7_6_m_corr[syndromeI][i]] ^= 1; // flip bit } } if (i == 0) { return false; } } return true; } // ======================================================================================== /* This function init all FEC functions * it must be called once at startup */ void InitAllFecFunction(void) { Hamming_7_4_init(); Hamming_12_8_init(); Hamming_13_9_init(); Hamming_15_11_init(); Hamming_16_11_4_init(); Golay_20_8_init(); Golay_23_12_init(); Golay_24_12_init(); QR_16_7_6_init(); } /* End InitAllFEC() */ /* End of file */