/* Iridium AMBE vocoder - ECC routines */ /* (C) 2015 by Sylvain Munaut * All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ /*! \addtogroup codec_private * @{ */ /*! \file codec/ecc.c * \brief Iridium AMBE vocoder ECC routines */ #ifdef HAVE_LIBOSMOCORE #include #else #include "compat_bits.h" #endif #include "ecc_tables.h" /* Local helpers ---------------------------------------------------------- */ /*! \brief Writes a given word as ubits (MSBs first) * \param[out] bits Pointer where to write the ubits * \param[in] word Word to write * \param[in] N Number of bits */ static void _ubit_write(ubit_t *bits, uint32_t word, int N) { int i, s; s = N - 1; for (i=0; i> s--) & 1; } /*! \brief Reads a word from ubits (MSBs first) * \param[in] bits Pointer where to read the ubits from * \param[in] N Number of bits * \returns The reconstructed value (unsigned) */ static uint32_t _ubit_read(ubit_t *bits, int N) { uint32_t rv = 0; int i; for (i=0; i> i) & 0xf]; return t; } /* Golay 23/12 & 24/12 ---------------------------------------------------- */ /*! \brief Computes Golay Syndrome of given word * \param[in] data Data word * \param[in] tbl Mask table to use * \returns Syndrome of 'data' using 'tbl' */ static uint32_t _golay_syndrome(uint32_t data, const uint32_t *tbl) { uint32_t syndrome, mask; int i; syndrome = 0; mask = 1<<11; for (i=0; i<12; i++) { if (data & mask) syndrome ^= tbl[i]; mask >>= 1; } return syndrome; } /*! \brief Encode one word using Golay 23/12 * \param[out] out 23 ubits output buffer * \param[in] in 12 ubits input buffer */ void ir77_ambe_golay23_encode(ubit_t *out, ubit_t *in) { uint32_t cw; cw = _ubit_read(in, 12); cw = (cw << 11) | _golay_syndrome(cw, _golay23_syn_tbl); _ubit_write(out, cw, 23); } /*! \brief Decode one word using Golay 23/12 code * \param[out] out 12 ubits output buffer * \param[in] in 23 ubits input buffer * \param[out] data_p Optional return pointer for the decoded word * \returns Number of bits errors */ int ir77_ambe_golay23_decode(ubit_t *out, ubit_t *in, uint32_t *data_p) { uint32_t cw, data, ecc_rx, ecc_ex, syn; int w = 0; cw = _ubit_read(in, 23); data = cw >> 11; ecc_rx = cw & 0x7ff; ecc_ex = _golay_syndrome(data, _golay23_syn_tbl); syn = ecc_ex ^ ecc_rx; if (syn) { uint32_t errors = _golay23_dec_tbl[syn]; data ^= errors >> 11; w = _weight(errors); } _ubit_write(out, data, 12); if (data_p) *data_p = data; return w; } /*! \brief Encode one word using Golay 24/12 * \param[out] out 24 ubits output buffer * \param[in] in 12 ubits input buffer */ void ir77_ambe_golay24_encode(ubit_t *out, ubit_t *in) { uint32_t cw; cw = _ubit_read(in, 12); cw = (cw << 12) | _golay_syndrome(cw, _golay24_syn_tbl); _ubit_write(out, cw, 24); } /*! \brief Decode one word using Golay 24/12 code * \param[out] out 12 ubits output buffer * \param[in] in 24 ubits input buffer * \param[out] data_p Optional return pointer for the decoded word * \returns Number of bits errors */ int ir77_ambe_golay24_decode(ubit_t *out, ubit_t *in, uint32_t *data_p) { uint32_t cw, data, ecc_rx, ecc_ex, syn; int w = 0; cw = _ubit_read(in, 24); data = cw >> 12; ecc_rx = cw & 0xfff; ecc_ex = _golay_syndrome(data, _golay24_syn_tbl); syn = ecc_ex ^ ecc_rx; if (syn) { uint32_t errors = _golay23_dec_tbl[syn >> 1]; data ^= errors >> 11; w = _weight(errors); //w += (syn & 1) ^ (w & 1); /* FIXME */ } _ubit_write(out, data, 12); if (data_p) *data_p = data; return w; } /* Hamming 15/11 codes ---------------------------------------------------- */ /*! \brief Computes Hamming 15/11 syndrome of a given value * \param[in] v Value * \returns Hamming 15/11 syndrome of 'v' */ static uint32_t _hamming1511_syndrome(uint32_t v) { uint32_t s = 0; int i; for (i=0; i<4; i++) { s <<= 1; s |= _weight(v & _ham1511_mask_tbl[i]) & 1; } return s; } /*! \brief Encode one word using Hamming 15/11 * \param[out] out 15 ubits output buffer * \param[in] in 11 ubits input buffer */ void ir77_ambe_hamming1511_encode(ubit_t *out, ubit_t *in) { uint32_t cw; cw = _ubit_read(in, 11) << 4; cw |= _hamming1511_syndrome(cw); _ubit_write(out, cw, 15); } /*! \brief Decode one word using Hamming 15/11 * \param[out] out 11 ubits output buffer * \param[in] in 15 ubits input buffer * \returns 0 if no errors, 1 if errors */ int ir77_ambe_hamming1511_decode(ubit_t *out, ubit_t *in) { uint32_t cw = _ubit_read(in, 15); uint32_t syndrome; int w = 0; syndrome = _hamming1511_syndrome(cw); if (syndrome) { cw ^= 1 << _ham1511_fix_tbl[syndrome]; w = 1; } _ubit_write(out, cw >> 4, 11); return w; } /*! @} */