merge upstream changes for AMBEFEC and Golay (this changes how audio FEC is done, and may cause artifacts on DMR and NXDN);

2.0-maint
Bryan Biedenkapp 3 years ago
parent 01ffa07c69
commit c4104d41ec

@ -11,8 +11,9 @@
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0) // Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
// //
/* /*
* Copyright (C) 2010,2014,2016 by Jonathan Naylor G4KLX * Copyright (C) 2010,2014,2016,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2016 Mathias Weyland, HB9FRV * Copyright (C) 2016 Mathias Weyland, HB9FRV
* Copyright (C) 2018-2022 by Bryan Biedenkapp N2PLL
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -32,6 +33,7 @@
#include "edac/AMBEFEC.h" #include "edac/AMBEFEC.h"
#include "edac/Golay24128.h" #include "edac/Golay24128.h"
#include "edac/Hamming.h" #include "edac/Hamming.h"
#include "Utils.h"
using namespace edac; using namespace edac;
@ -72,24 +74,12 @@ uint32_t AMBEFEC::regenerateDMR(uint8_t* bytes) const
uint32_t c1 = 0U, c2 = 0U, c3 = 0U; uint32_t c1 = 0U, c2 = 0U, c3 = 0U;
uint32_t MASK = 0x800000U; uint32_t MASK = 0x800000U;
for (uint32_t i = 0U; i < 24U; i++) { for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) {
uint32_t a1Pos = DMR_A_TABLE[i]; uint32_t a1Pos = AMBE_A_TABLE[i];
uint32_t b1Pos = DMR_B_TABLE[i];
uint32_t c1Pos = DMR_C_TABLE[i];
uint32_t a2Pos = a1Pos + 72U; uint32_t a2Pos = a1Pos + 72U;
if (a2Pos >= 108U) if (a2Pos >= 108U)
a2Pos += 48U; a2Pos += 48U;
uint32_t b2Pos = b1Pos + 72U;
if (b2Pos >= 108U)
b2Pos += 48U;
uint32_t c2Pos = c1Pos + 72U;
if (c2Pos >= 108U)
c2Pos += 48U;
uint32_t a3Pos = a1Pos + 192U; uint32_t a3Pos = a1Pos + 192U;
uint32_t b3Pos = b1Pos + 192U;
uint32_t c3Pos = c1Pos + 192U;
if (READ_BIT(bytes, a1Pos)) if (READ_BIT(bytes, a1Pos))
a1 |= MASK; a1 |= MASK;
@ -97,57 +87,81 @@ uint32_t AMBEFEC::regenerateDMR(uint8_t* bytes) const
a2 |= MASK; a2 |= MASK;
if (READ_BIT(bytes, a3Pos)) if (READ_BIT(bytes, a3Pos))
a3 |= MASK; a3 |= MASK;
}
MASK = 0x400000U;
for (uint32_t i = 0U; i < 23U; i++, MASK >>= 1) {
uint32_t b1Pos = AMBE_B_TABLE[i];
uint32_t b2Pos = b1Pos + 72U;
if (b2Pos >= 108U)
b2Pos += 48U;
uint32_t b3Pos = b1Pos + 192U;
if (READ_BIT(bytes, b1Pos)) if (READ_BIT(bytes, b1Pos))
b1 |= MASK; b1 |= MASK;
if (READ_BIT(bytes, b2Pos)) if (READ_BIT(bytes, b2Pos))
b2 |= MASK; b2 |= MASK;
if (READ_BIT(bytes, b3Pos)) if (READ_BIT(bytes, b3Pos))
b3 |= MASK; b3 |= MASK;
if (READ_BIT(bytes, c1Pos))
c1 |= MASK;
if (READ_BIT(bytes, c2Pos))
c2 |= MASK;
if (READ_BIT(bytes, c3Pos))
c3 |= MASK;
MASK >>= 1;
} }
uint32_t errors = regenerate(a1, b1, c1, true); MASK = 0x1000000U;
errors += regenerate(a2, b2, c2, true); for (uint32_t i = 0U; i < 25U; i++, MASK >>= 1) {
errors += regenerate(a3, b3, c3, true); uint32_t c1Pos = AMBE_C_TABLE[i];
uint32_t c2Pos = c1Pos + 72U;
if (c2Pos >= 108U)
c2Pos += 48U;
uint32_t c3Pos = c1Pos + 192U;
if (READ_BIT(bytes, c1Pos))
c1 |= MASK;
if (READ_BIT(bytes, c2Pos))
c2 |= MASK;
if (READ_BIT(bytes, c3Pos))
c3 |= MASK;
}
uint32_t errors = regenerate(a1, b1, c1);
errors += regenerate(a2, b2, c2);
errors += regenerate(a3, b3, c3);
MASK = 0x800000U; MASK = 0x800000U;
for (uint32_t i = 0U; i < 24U; i++) { for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) {
uint32_t a1Pos = DMR_A_TABLE[i]; uint32_t a1Pos = AMBE_A_TABLE[i];
uint32_t b1Pos = DMR_B_TABLE[i];
uint32_t c1Pos = DMR_C_TABLE[i];
uint32_t a2Pos = a1Pos + 72U; uint32_t a2Pos = a1Pos + 72U;
if (a2Pos >= 108U) if (a2Pos >= 108U)
a2Pos += 48U; a2Pos += 48U;
uint32_t b2Pos = b1Pos + 72U;
if (b2Pos >= 108U)
b2Pos += 48U;
uint32_t c2Pos = c1Pos + 72U;
if (c2Pos >= 108U)
c2Pos += 48U;
uint32_t a3Pos = a1Pos + 192U; uint32_t a3Pos = a1Pos + 192U;
uint32_t b3Pos = b1Pos + 192U;
uint32_t c3Pos = c1Pos + 192U;
WRITE_BIT(bytes, a1Pos, a1 & MASK); WRITE_BIT(bytes, a1Pos, a1 & MASK);
WRITE_BIT(bytes, a2Pos, a2 & MASK); WRITE_BIT(bytes, a2Pos, a2 & MASK);
WRITE_BIT(bytes, a3Pos, a3 & MASK); WRITE_BIT(bytes, a3Pos, a3 & MASK);
}
MASK = 0x400000U;
for (uint32_t i = 0U; i < 23U; i++, MASK >>= 1) {
uint32_t b1Pos = AMBE_B_TABLE[i];
uint32_t b2Pos = b1Pos + 72U;
if (b2Pos >= 108U)
b2Pos += 48U;
uint32_t b3Pos = b1Pos + 192U;
WRITE_BIT(bytes, b1Pos, b1 & MASK); WRITE_BIT(bytes, b1Pos, b1 & MASK);
WRITE_BIT(bytes, b2Pos, b2 & MASK); WRITE_BIT(bytes, b2Pos, b2 & MASK);
WRITE_BIT(bytes, b3Pos, b3 & MASK); WRITE_BIT(bytes, b3Pos, b3 & MASK);
}
MASK = 0x1000000U;
for (uint32_t i = 0U; i < 25U; i++, MASK >>= 1) {
uint32_t c1Pos = AMBE_C_TABLE[i];
uint32_t c2Pos = c1Pos + 72U;
if (c2Pos >= 108U)
c2Pos += 48U;
uint32_t c3Pos = c1Pos + 192U;
WRITE_BIT(bytes, c1Pos, c1 & MASK); WRITE_BIT(bytes, c1Pos, c1 & MASK);
WRITE_BIT(bytes, c2Pos, c2 & MASK); WRITE_BIT(bytes, c2Pos, c2 & MASK);
WRITE_BIT(bytes, c3Pos, c3 & MASK); WRITE_BIT(bytes, c3Pos, c3 & MASK);
MASK >>= 1;
} }
return errors; return errors;
@ -167,24 +181,12 @@ uint32_t AMBEFEC::measureDMRBER(const uint8_t* bytes) const
uint32_t c1 = 0U, c2 = 0U, c3 = 0U; uint32_t c1 = 0U, c2 = 0U, c3 = 0U;
uint32_t MASK = 0x800000U; uint32_t MASK = 0x800000U;
for (uint32_t i = 0U; i < 24U; i++) { for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) {
uint32_t a1Pos = DMR_A_TABLE[i]; uint32_t a1Pos = AMBE_A_TABLE[i];
uint32_t b1Pos = DMR_B_TABLE[i];
uint32_t c1Pos = DMR_C_TABLE[i];
uint32_t a2Pos = a1Pos + 72U; uint32_t a2Pos = a1Pos + 72U;
if (a2Pos >= 108U) if (a2Pos >= 108U)
a2Pos += 48U; a2Pos += 48U;
uint32_t b2Pos = b1Pos + 72U;
if (b2Pos >= 108U)
b2Pos += 48U;
uint32_t c2Pos = c1Pos + 72U;
if (c2Pos >= 108U)
c2Pos += 48U;
uint32_t a3Pos = a1Pos + 192U; uint32_t a3Pos = a1Pos + 192U;
uint32_t b3Pos = b1Pos + 192U;
uint32_t c3Pos = c1Pos + 192U;
if (READ_BIT(bytes, a1Pos)) if (READ_BIT(bytes, a1Pos))
a1 |= MASK; a1 |= MASK;
@ -192,25 +194,43 @@ uint32_t AMBEFEC::measureDMRBER(const uint8_t* bytes) const
a2 |= MASK; a2 |= MASK;
if (READ_BIT(bytes, a3Pos)) if (READ_BIT(bytes, a3Pos))
a3 |= MASK; a3 |= MASK;
}
MASK = 0x400000U;
for (uint32_t i = 0U; i < 23U; i++, MASK >>= 1) {
uint32_t b1Pos = AMBE_B_TABLE[i];
uint32_t b2Pos = b1Pos + 72U;
if (b2Pos >= 108U)
b2Pos += 48U;
uint32_t b3Pos = b1Pos + 192U;
if (READ_BIT(bytes, b1Pos)) if (READ_BIT(bytes, b1Pos))
b1 |= MASK; b1 |= MASK;
if (READ_BIT(bytes, b2Pos)) if (READ_BIT(bytes, b2Pos))
b2 |= MASK; b2 |= MASK;
if (READ_BIT(bytes, b3Pos)) if (READ_BIT(bytes, b3Pos))
b3 |= MASK; b3 |= MASK;
if (READ_BIT(bytes, c1Pos))
c1 |= MASK;
if (READ_BIT(bytes, c2Pos))
c2 |= MASK;
if (READ_BIT(bytes, c3Pos))
c3 |= MASK;
MASK >>= 1;
} }
uint32_t errors = regenerate(a1, b1, c1, true); MASK = 0x1000000U;
errors += regenerate(a2, b2, c2, true); for (uint32_t i = 0U; i < 25U; i++, MASK >>= 1) {
errors += regenerate(a3, b3, c3, true); uint32_t c1Pos = AMBE_C_TABLE[i];
uint32_t c2Pos = c1Pos + 72U;
if (c2Pos >= 108U)
c2Pos += 48U;
uint32_t c3Pos = c1Pos + 192U;
if (READ_BIT(bytes, c1Pos))
c1 |= MASK;
if (READ_BIT(bytes, c2Pos))
c2 |= MASK;
if (READ_BIT(bytes, c3Pos))
c3 |= MASK;
}
uint32_t errors = regenerate(a1, b1, c1);
errors += regenerate(a2, b2, c2);
errors += regenerate(a3, b3, c3);
return errors; return errors;
} }
@ -499,7 +519,7 @@ uint32_t AMBEFEC::regenerateNXDN(uint8_t* bytes) const
uint32_t a = 0U; uint32_t a = 0U;
uint32_t MASK = 0x800000U; uint32_t MASK = 0x800000U;
for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) { for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) {
uint32_t aPos = DMR_A_TABLE[i]; uint32_t aPos = AMBE_A_TABLE[i];
if (READ_BIT(bytes, aPos)) if (READ_BIT(bytes, aPos))
a |= MASK; a |= MASK;
} }
@ -507,7 +527,7 @@ uint32_t AMBEFEC::regenerateNXDN(uint8_t* bytes) const
uint32_t b = 0U; uint32_t b = 0U;
MASK = 0x400000U; MASK = 0x400000U;
for (uint32_t i = 0U; i < 23U; i++, MASK >>= 1) { for (uint32_t i = 0U; i < 23U; i++, MASK >>= 1) {
uint32_t bPos = DMR_B_TABLE[i]; uint32_t bPos = AMBE_B_TABLE[i];
if (READ_BIT(bytes, bPos)) if (READ_BIT(bytes, bPos))
b |= MASK; b |= MASK;
} }
@ -515,34 +535,72 @@ uint32_t AMBEFEC::regenerateNXDN(uint8_t* bytes) const
uint32_t c = 0U; uint32_t c = 0U;
MASK = 0x1000000U; MASK = 0x1000000U;
for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) { for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) {
uint32_t cPos = DMR_C_TABLE[i]; uint32_t cPos = AMBE_C_TABLE[i];
if (READ_BIT(bytes, cPos)) if (READ_BIT(bytes, cPos))
c |= MASK; c |= MASK;
} }
uint32_t errors = regenerate(a, b, c, true); uint32_t errors = regenerate(a, b, c);
MASK = 0x800000U; MASK = 0x800000U;
for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) { for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) {
uint32_t aPos = DMR_A_TABLE[i]; uint32_t aPos = AMBE_A_TABLE[i];
WRITE_BIT(bytes, aPos, a & MASK); WRITE_BIT(bytes, aPos, a & MASK);
} }
MASK = 0x400000U; MASK = 0x400000U;
for (uint32_t i = 0U; i < 23U; i++, MASK >>= 1) { for (uint32_t i = 0U; i < 23U; i++, MASK >>= 1) {
uint32_t bPos = DMR_B_TABLE[i]; uint32_t bPos = AMBE_B_TABLE[i];
WRITE_BIT(bytes, bPos, b & MASK); WRITE_BIT(bytes, bPos, b & MASK);
} }
MASK = 0x1000000U; MASK = 0x1000000U;
for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) { for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) {
uint32_t cPos = DMR_C_TABLE[i]; uint32_t cPos = AMBE_C_TABLE[i];
WRITE_BIT(bytes, cPos, c & MASK); WRITE_BIT(bytes, cPos, c & MASK);
} }
return errors; return errors;
} }
/// <summary>
/// Returns the number of errors on the NXDN BER input bytes.
/// </summary>
/// <param name="bytes"></param>
/// <returns>Count of errors.</returns>
uint32_t AMBEFEC::measureNXDNBER(uint8_t* bytes) const
{
assert(bytes != NULL);
uint32_t a = 0U;
uint32_t MASK = 0x800000U;
for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) {
uint32_t aPos = AMBE_A_TABLE[i];
if (READ_BIT(bytes, aPos))
a |= MASK;
}
uint32_t b = 0U;
MASK = 0x400000U;
for (uint32_t i = 0U; i < 23U; i++, MASK >>= 1) {
uint32_t bPos = AMBE_B_TABLE[i];
if (READ_BIT(bytes, bPos))
b |= MASK;
}
uint32_t c = 0U;
MASK = 0x1000000U;
for (uint32_t i = 0U; i < 24U; i++, MASK >>= 1) {
uint32_t cPos = AMBE_C_TABLE[i];
if (READ_BIT(bytes, cPos))
c |= MASK;
}
uint32_t errors = regenerate(a, b, c);
return errors;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Private Class Members // Private Class Members
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -553,60 +611,44 @@ uint32_t AMBEFEC::regenerateNXDN(uint8_t* bytes) const
/// <param name="a"></param> /// <param name="a"></param>
/// <param name="b"></param> /// <param name="b"></param>
/// <param name="c"></param> /// <param name="c"></param>
/// <param name="b23"></param> /// <param name="ignoreParity"></param>
/// <returns></returns> /// <returns></returns>
uint32_t AMBEFEC::regenerate(uint32_t& a, uint32_t& b, uint32_t& c, bool b23) const uint32_t AMBEFEC::regenerate(uint32_t& a, uint32_t& b, uint32_t& c, bool ignoreParity) const
{ {
uint32_t old_a = a; uint32_t old_a = a;
uint32_t old_b = b; uint32_t old_b = b;
// For the b23 bypass
bool b24 = (b & 0x01U) == 0x01U;
uint32_t data = Golay24128::decode24128(a); uint32_t data;
bool valid = Golay24128::decode24128(a, data);
if (!valid && !ignoreParity) {
a = 0xF00292U;
b = 0x0E0B20U;
c = 0x000000U;
return 10U; // An invalid A block gives an error count of 10
}
uint32_t new_a = Golay24128::encode24128(data); a = Golay24128::encode24128(data);
// The PRNG // PRNG
uint32_t p = PRNG_TABLE[data]; uint32_t p = PRNG_TABLE[data] >> 1;
b ^= p;
b ^= p; uint32_t datb = Golay24128::decode23127(b);
b = Golay24128::encode23127(datb) >> 1;
uint32_t datb = Golay24128::decode24128(b); b ^= p;
uint32_t new_b = Golay24128::encode24128(datb); uint32_t v = a ^ old_a;
uint32_t errsA = Utils::countBits32(v);
new_b ^= p;
if (b23) {
new_b &= 0xFFFFFEU;
new_b |= b24 ? 0x01U : 0x00U;
}
uint32_t errsA = 0U, errsB = 0U; v = b ^ old_b;
uint32_t errsB = Utils::countBits32(v);
uint32_t v = new_a ^ old_a;
while (v != 0U) {
v &= v - 1U;
errsA++;
}
v = new_b ^ old_b;
while (v != 0U) {
v &= v - 1U;
errsB++;
}
if (b23) {
if (errsA >= 4U || ((errsA + errsB) >= 6U && errsA >= 2U)) {
a = 0xF00292U;
b = 0x0E0B20U;
c = 0x000000U;
}
}
a = new_a; if (errsA >= 4U || ((errsA + errsB) >= 6U && errsA >= 2U)) {
b = new_b; a = 0xF00292U;
b = 0x0E0B20U;
c = 0x000000U;
}
return errsA + errsB; return errsA + errsB;
} }

@ -11,7 +11,8 @@
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0) // Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
// //
/* /*
* Copyright (C) 2010,2014,2016 by Jonathan Naylor G4KLX * Copyright (C) 2010,2014,2016,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2018-2022 by Bryan Biedenkapp N2PLL
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -450,15 +451,15 @@ namespace edac
0xECDB0FU, 0xB542DAU, 0x9E5131U, 0xC7ABA5U, 0x8C38FEU, 0x97010BU, 0xDED290U, 0xA4CC7DU, 0xAD3D2EU, 0xF6B6B3U, 0xECDB0FU, 0xB542DAU, 0x9E5131U, 0xC7ABA5U, 0x8C38FEU, 0x97010BU, 0xDED290U, 0xA4CC7DU, 0xAD3D2EU, 0xF6B6B3U,
0xF9A540U, 0x205ED9U, 0x634EB6U, 0x5A9567U, 0x11A6D8U, 0x0B3F09U }; 0xF9A540U, 0x205ED9U, 0x634EB6U, 0x5A9567U, 0x11A6D8U, 0x0B3F09U };
const uint32_t DMR_A_TABLE[] = { const uint32_t AMBE_A_TABLE[] = {
0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U, 0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U,
48U, 52U, 56U, 60U, 64U, 68U, 1U, 5U, 9U, 13U, 17U, 21U }; 48U, 52U, 56U, 60U, 64U, 68U, 1U, 5U, 9U, 13U, 17U, 21U };
const uint32_t DMR_B_TABLE[] = { const uint32_t AMBE_B_TABLE[] = {
25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, 25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U,
2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U, 46U }; 2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U };
const uint32_t DMR_C_TABLE[] = { const uint32_t AMBE_C_TABLE[] = {
50U, 54U, 58U, 62U, 66U, 70U, 3U, 7U, 11U, 15U, 19U, 23U, 46U, 50U, 54U, 58U, 62U, 66U, 70U, 3U, 7U, 11U, 15U, 19U,
27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U }; 23U, 27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U };
const uint32_t IMBE_INTERLEAVE[] = { const uint32_t IMBE_INTERLEAVE[] = {
0, 7, 12, 19, 24, 31, 36, 43, 48, 55, 60, 67, 72, 79, 84, 91, 96, 103, 108, 115, 120, 127, 132, 139, 0, 7, 12, 19, 24, 31, 36, 43, 48, 55, 60, 67, 72, 79, 84, 91, 96, 103, 108, 115, 120, 127, 132, 139,
@ -493,10 +494,12 @@ namespace edac
/// <summary>Regenerates the NXDN AMBE FEC for the input bytes.</summary> /// <summary>Regenerates the NXDN AMBE FEC for the input bytes.</summary>
uint32_t regenerateNXDN(uint8_t* bytes) const; uint32_t regenerateNXDN(uint8_t* bytes) const;
/// <summary>Returns the number of errors on the NXDN BER input bytes.</summary>
uint32_t measureNXDNBER(uint8_t* bytes) const;
private: private:
/// <summary></summary> /// <summary></summary>
uint32_t regenerate(uint32_t& a, uint32_t& b, uint32_t& c, bool b23) const; uint32_t regenerate(uint32_t& a, uint32_t& b, uint32_t& c, bool ignoreParity = true) const;
}; };
} // namespace edac } // namespace edac

@ -31,6 +31,7 @@
*/ */
#include "Defines.h" #include "Defines.h"
#include "edac/Golay24128.h" #include "edac/Golay24128.h"
#include "Utils.h"
using namespace edac; using namespace edac;
@ -1100,28 +1101,33 @@ uint32_t Golay24128::decode23127(uint32_t code)
/// Decode Golay (24,12,8) FEC. /// Decode Golay (24,12,8) FEC.
/// </summary> /// </summary>
/// <param name="code"></param> /// <param name="code"></param>
/// <param name="out"></param>
/// <returns></returns> /// <returns></returns>
uint32_t Golay24128::decode24128(uint32_t code) bool Golay24128::decode24128(uint32_t code, uint32_t& out)
{ {
return decode23127(code >> 1); uint32_t syndrome = getSyndrome23127(code >> 1);
uint32_t error_pattern = DECODING_TABLE_23127[syndrome] << 1;
out = code ^ error_pattern;
bool valid = (Utils::countBits32(syndrome) < 3U) || !(Utils::countBits32(out) & 1);
out >>= 12;
return valid;
} }
/// <summary> /// <summary>
/// Decode Golay (24,12,8) FEC. /// Decode Golay (24,12,8) FEC.
/// </summary> /// </summary>
/// <param name="data">Golay FEC encoded data byte array</param> /// <param name="bytes">Golay FEC encoded data byte array</param>
/// <param name="out"></param>
/// <returns></returns> /// <returns></returns>
uint32_t Golay24128::decode24128(uint8_t* bytes) bool Golay24128::decode24128(uint8_t* bytes, uint32_t& out)
{ {
assert(bytes != NULL); assert(bytes != NULL);
uint32_t code = bytes[0U]; uint32_t code = (bytes[0U] << 16) | (bytes[1U] << 8) | (bytes[2U] << 0);
code <<= 8; return decode24128(code, out);
code |= bytes[1U];
code <<= 8;
code |= bytes[2U];
return decode23127(code >> 1);
} }
/// <summary> /// <summary>
@ -1156,8 +1162,8 @@ void Golay24128::decode24128(uint8_t* data, const uint8_t* raw, uint32_t msglen)
v1 = ((r3 << 16) & 0xff0000) | ((r4 << 8) & 0x00ff00) | ((r5 << 0) & 0x0000ff); v1 = ((r3 << 16) & 0xff0000) | ((r4 << 8) & 0x00ff00) | ((r5 << 0) & 0x0000ff);
// decode each symbol into a 12-bit symbol // decode each symbol into a 12-bit symbol
m0_hat = decode24128(v0); decode24128(v0, m0_hat);
m1_hat = decode24128(v1); decode24128(v1, m1_hat);
// unpack two 12-bit symbols into three 8-bit bytes // unpack two 12-bit symbols into three 8-bit bytes
data[i + 0] = ((m0_hat >> 4) & 0xff); data[i + 0] = ((m0_hat >> 4) & 0xff);
@ -1178,7 +1184,7 @@ void Golay24128::decode24128(uint8_t* data, const uint8_t* raw, uint32_t msglen)
v0 = ((r0 << 16) & 0xff0000) | ((r1 << 8) & 0x00ff00) | ((r2) & 0x0000ff); v0 = ((r0 << 16) & 0xff0000) | ((r1 << 8) & 0x00ff00) | ((r2) & 0x0000ff);
// decode into a 12-bit symbol // decode into a 12-bit symbol
m0_hat = decode24128(v0); decode24128(v0, m0_hat);
// retain last 8 bits of 12-bit symbol // retain last 8 bits of 12-bit symbol
data[i] = m0_hat & 0xff; data[i] = m0_hat & 0xff;

@ -11,8 +11,8 @@
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0) // Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
// //
/* /*
* Copyright (C) 2010,2016 by Jonathan Naylor G4KLX * Copyright (C) 2010,2016,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Bryan Biedenkapp N2PLL * Copyright (C) 2017,2022 by Bryan Biedenkapp N2PLL
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -46,9 +46,9 @@ namespace edac
/// <summary>Decode Golay (23,12,7) FEC.</summary> /// <summary>Decode Golay (23,12,7) FEC.</summary>
static uint32_t decode23127(uint32_t code); static uint32_t decode23127(uint32_t code);
/// <summary>Decode Golay (24,12,8) FEC.</summary> /// <summary>Decode Golay (24,12,8) FEC.</summary>
static uint32_t decode24128(uint32_t code); static bool decode24128(uint32_t code, uint32_t& out);
/// <summary>Decode Golay (24,12,8) FEC.</summary> /// <summary>Decode Golay (24,12,8) FEC.</summary>
static uint32_t decode24128(uint8_t* bytes); static bool decode24128(uint8_t* bytes, uint32_t& out);
/// <summary>Decode Golay (24,12,8) FEC.</summary> /// <summary>Decode Golay (24,12,8) FEC.</summary>
static void decode24128(uint8_t* data, const uint8_t* raw, uint32_t msglen); static void decode24128(uint8_t* data, const uint8_t* raw, uint32_t msglen);

@ -768,7 +768,10 @@ void LC::decodeHDUGolay(const uint8_t * data, uint8_t * raw)
uint32_t g0 = 0U; uint32_t g0 = 0U;
for (uint32_t j = 0U; j < 18U; j++) for (uint32_t j = 0U; j < 18U; j++)
g0 = (g0 << 1) | (golay[j] ? 0x01U : 0x00U); g0 = (g0 << 1) | (golay[j] ? 0x01U : 0x00U);
uint32_t c0data = edac::Golay24128::decode24128(g0);
uint32_t c0data = 0U;
edac::Golay24128::decode24128(g0, c0data);
for (int j = 5; j >= 0; j--) { for (int j = 5; j >= 0; j--) {
golay[j] = (c0data & 0x01U) == 0x01U; golay[j] = (c0data & 0x01U) == 0x01U;
c0data >>= 1; c0data >>= 1;

Loading…
Cancel
Save

Powered by TurnKey Linux.