Restoring AMBE FEC improvement + fix
This commit is contained in:
parent
9550b790a7
commit
25bd10fa7d
2 changed files with 127 additions and 90 deletions
212
AMBEFEC.cpp
212
AMBEFEC.cpp
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010,2014,2016 by Jonathan Naylor G4KLX
|
* Copyright (C) 2010,2014,2016,2018 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 Mathias Weyland, HB9FRV
|
* Copyright (C) 2016 Mathias Weyland, HB9FRV
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -21,8 +21,6 @@
|
||||||
#include "Hamming.h"
|
#include "Hamming.h"
|
||||||
#include "AMBEFEC.h"
|
#include "AMBEFEC.h"
|
||||||
|
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
@ -446,9 +444,9 @@ const unsigned int PRNG_TABLE[] = {
|
||||||
const unsigned int DMR_A_TABLE[] = { 0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U,
|
const unsigned int DMR_A_TABLE[] = { 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 unsigned int DMR_B_TABLE[] = {25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U,
|
const unsigned int DMR_B_TABLE[] = {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 unsigned int DMR_C_TABLE[] = {50U, 54U, 58U, 62U, 66U, 70U, 3U, 7U, 11U, 15U, 19U, 23U,
|
const unsigned int DMR_C_TABLE[] = {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 unsigned int DSTAR_A_TABLE[] = {0U, 6U, 12U, 18U, 24U, 30U, 36U, 42U, 48U, 54U, 60U, 66U,
|
const unsigned int DSTAR_A_TABLE[] = {0U, 6U, 12U, 18U, 24U, 30U, 36U, 42U, 48U, 54U, 60U, 66U,
|
||||||
1U, 7U, 13U, 19U, 25U, 31U, 37U, 43U, 49U, 55U, 61U, 67U};
|
1U, 7U, 13U, 19U, 25U, 31U, 37U, 43U, 49U, 55U, 61U, 67U};
|
||||||
|
@ -479,28 +477,13 @@ unsigned int CAMBEFEC::regenerateDMR(unsigned char* bytes) const
|
||||||
assert(bytes != NULL);
|
assert(bytes != NULL);
|
||||||
|
|
||||||
unsigned int a1 = 0U, a2 = 0U, a3 = 0U;
|
unsigned int a1 = 0U, a2 = 0U, a3 = 0U;
|
||||||
unsigned int b1 = 0U, b2 = 0U, b3 = 0U;
|
|
||||||
unsigned int c1 = 0U, c2 = 0U, c3 = 0U;
|
|
||||||
|
|
||||||
unsigned int MASK = 0x800000U;
|
unsigned int MASK = 0x800000U;
|
||||||
for (unsigned int i = 0U; i < 24U; i++) {
|
for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) {
|
||||||
unsigned int a1Pos = DMR_A_TABLE[i];
|
unsigned int a1Pos = DMR_A_TABLE[i];
|
||||||
unsigned int b1Pos = DMR_B_TABLE[i];
|
|
||||||
unsigned int c1Pos = DMR_C_TABLE[i];
|
|
||||||
|
|
||||||
unsigned int a2Pos = a1Pos + 72U;
|
unsigned int a2Pos = a1Pos + 72U;
|
||||||
if (a2Pos >= 108U)
|
if (a2Pos >= 108U)
|
||||||
a2Pos += 48U;
|
a2Pos += 48U;
|
||||||
unsigned int b2Pos = b1Pos + 72U;
|
|
||||||
if (b2Pos >= 108U)
|
|
||||||
b2Pos += 48U;
|
|
||||||
unsigned int c2Pos = c1Pos + 72U;
|
|
||||||
if (c2Pos >= 108U)
|
|
||||||
c2Pos += 48U;
|
|
||||||
|
|
||||||
unsigned int a3Pos = a1Pos + 192U;
|
unsigned int a3Pos = a1Pos + 192U;
|
||||||
unsigned int b3Pos = b1Pos + 192U;
|
|
||||||
unsigned int c3Pos = c1Pos + 192U;
|
|
||||||
|
|
||||||
if (READ_BIT(bytes, a1Pos))
|
if (READ_BIT(bytes, a1Pos))
|
||||||
a1 |= MASK;
|
a1 |= MASK;
|
||||||
|
@ -508,57 +491,83 @@ unsigned int CAMBEFEC::regenerateDMR(unsigned char* bytes) const
|
||||||
a2 |= MASK;
|
a2 |= MASK;
|
||||||
if (READ_BIT(bytes, a3Pos))
|
if (READ_BIT(bytes, a3Pos))
|
||||||
a3 |= MASK;
|
a3 |= MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int b1 = 0U, b2 = 0U, b3 = 0U;
|
||||||
|
MASK = 0x400000U;
|
||||||
|
for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) {
|
||||||
|
unsigned int b1Pos = DMR_B_TABLE[i];
|
||||||
|
unsigned int b2Pos = b1Pos + 72U;
|
||||||
|
if (b2Pos >= 108U)
|
||||||
|
b2Pos += 48U;
|
||||||
|
unsigned int 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int c1 = 0U, c2 = 0U, c3 = 0U;
|
||||||
|
MASK = 0x1000000U;
|
||||||
|
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
|
||||||
|
unsigned int c1Pos = DMR_C_TABLE[i];
|
||||||
|
unsigned int c2Pos = c1Pos + 72U;
|
||||||
|
if (c2Pos >= 108U)
|
||||||
|
c2Pos += 48U;
|
||||||
|
unsigned int c3Pos = c1Pos + 192U;
|
||||||
|
|
||||||
if (READ_BIT(bytes, c1Pos))
|
if (READ_BIT(bytes, c1Pos))
|
||||||
c1 |= MASK;
|
c1 |= MASK;
|
||||||
if (READ_BIT(bytes, c2Pos))
|
if (READ_BIT(bytes, c2Pos))
|
||||||
c2 |= MASK;
|
c2 |= MASK;
|
||||||
if (READ_BIT(bytes, c3Pos))
|
if (READ_BIT(bytes, c3Pos))
|
||||||
c3 |= MASK;
|
c3 |= MASK;
|
||||||
|
|
||||||
MASK >>= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int errors = regenerate(a1, b1, c1, true);
|
unsigned int errors = regenerateDMR(a1, b1);
|
||||||
errors += regenerate(a2, b2, c2, true);
|
errors += regenerateDMR(a2, b2);
|
||||||
errors += regenerate(a3, b3, c3, true);
|
errors += regenerateDMR(a3, b3);
|
||||||
|
|
||||||
MASK = 0x800000U;
|
MASK = 0x800000U;
|
||||||
for (unsigned int i = 0U; i < 24U; i++) {
|
for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) {
|
||||||
unsigned int a1Pos = DMR_A_TABLE[i];
|
unsigned int a1Pos = DMR_A_TABLE[i];
|
||||||
unsigned int b1Pos = DMR_B_TABLE[i];
|
|
||||||
unsigned int c1Pos = DMR_C_TABLE[i];
|
|
||||||
|
|
||||||
unsigned int a2Pos = a1Pos + 72U;
|
unsigned int a2Pos = a1Pos + 72U;
|
||||||
if (a2Pos >= 108U)
|
if (a2Pos >= 108U)
|
||||||
a2Pos += 48U;
|
a2Pos += 48U;
|
||||||
unsigned int b2Pos = b1Pos + 72U;
|
|
||||||
if (b2Pos >= 108U)
|
|
||||||
b2Pos += 48U;
|
|
||||||
unsigned int c2Pos = c1Pos + 72U;
|
|
||||||
if (c2Pos >= 108U)
|
|
||||||
c2Pos += 48U;
|
|
||||||
|
|
||||||
unsigned int a3Pos = a1Pos + 192U;
|
unsigned int a3Pos = a1Pos + 192U;
|
||||||
unsigned int b3Pos = b1Pos + 192U;
|
|
||||||
unsigned int 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 (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) {
|
||||||
|
unsigned int b1Pos = DMR_B_TABLE[i];
|
||||||
|
unsigned int b2Pos = b1Pos + 72U;
|
||||||
|
if (b2Pos >= 108U)
|
||||||
|
b2Pos += 48U;
|
||||||
|
unsigned int 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 (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
|
||||||
|
unsigned int c1Pos = DMR_C_TABLE[i];
|
||||||
|
unsigned int c2Pos = c1Pos + 72U;
|
||||||
|
if (c2Pos >= 108U)
|
||||||
|
c2Pos += 48U;
|
||||||
|
unsigned int 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;
|
||||||
|
@ -583,7 +592,7 @@ unsigned int CAMBEFEC::regenerateDStar(unsigned char* bytes) const
|
||||||
MASK >>= 1;
|
MASK >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int errors = regenerate(a, b, c, false);
|
unsigned int errors = regenerateDStar(a, b);
|
||||||
|
|
||||||
MASK = 0x800000U;
|
MASK = 0x800000U;
|
||||||
for (unsigned int i = 0U; i < 24U; i++) {
|
for (unsigned int i = 0U; i < 24U; i++) {
|
||||||
|
@ -601,38 +610,47 @@ unsigned int CAMBEFEC::regenerateYSFDN(unsigned char* bytes) const
|
||||||
assert(bytes != NULL);
|
assert(bytes != NULL);
|
||||||
|
|
||||||
unsigned int a = 0U;
|
unsigned int a = 0U;
|
||||||
unsigned int b = 0U;
|
|
||||||
unsigned int c = 0U;
|
|
||||||
|
|
||||||
unsigned int MASK = 0x800000U;
|
unsigned int MASK = 0x800000U;
|
||||||
for (unsigned int i = 0U; i < 24U; i++) {
|
for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) {
|
||||||
unsigned int aPos = DMR_A_TABLE[i];
|
unsigned int aPos = DMR_A_TABLE[i];
|
||||||
unsigned int bPos = DMR_B_TABLE[i];
|
|
||||||
unsigned int cPos = DMR_C_TABLE[i];
|
|
||||||
|
|
||||||
if (READ_BIT(bytes, aPos))
|
if (READ_BIT(bytes, aPos))
|
||||||
a |= MASK;
|
a |= MASK;
|
||||||
if (READ_BIT(bytes, bPos))
|
|
||||||
b |= MASK;
|
|
||||||
if (READ_BIT(bytes, cPos))
|
|
||||||
c |= MASK;
|
|
||||||
|
|
||||||
MASK >>= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int errors = regenerate(a, b, c, true);
|
unsigned int b = 0U;
|
||||||
|
MASK = 0x400000U;
|
||||||
|
for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) {
|
||||||
|
unsigned int bPos = DMR_B_TABLE[i];
|
||||||
|
if (READ_BIT(bytes, bPos))
|
||||||
|
b |= MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int c = 0U;
|
||||||
|
MASK = 0x1000000U;
|
||||||
|
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
|
||||||
|
unsigned int cPos = DMR_C_TABLE[i];
|
||||||
|
if (READ_BIT(bytes, cPos))
|
||||||
|
c |= MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int errors = regenerateDMR(a, b);
|
||||||
|
|
||||||
MASK = 0x800000U;
|
MASK = 0x800000U;
|
||||||
for (unsigned int i = 0U; i < 24U; i++) {
|
for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) {
|
||||||
unsigned int aPos = DMR_A_TABLE[i];
|
unsigned int aPos = DMR_A_TABLE[i];
|
||||||
unsigned int bPos = DMR_B_TABLE[i];
|
|
||||||
unsigned int cPos = DMR_C_TABLE[i];
|
|
||||||
|
|
||||||
WRITE_BIT(bytes, aPos, a & MASK);
|
WRITE_BIT(bytes, aPos, a & MASK);
|
||||||
WRITE_BIT(bytes, bPos, b & MASK);
|
}
|
||||||
WRITE_BIT(bytes, cPos, c & MASK);
|
|
||||||
|
|
||||||
MASK >>= 1;
|
MASK = 0x400000U;
|
||||||
|
for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) {
|
||||||
|
unsigned int bPos = DMR_B_TABLE[i];
|
||||||
|
WRITE_BIT(bytes, bPos, b & MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
MASK = 0x1000000U;
|
||||||
|
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
|
||||||
|
unsigned int cPos = DMR_C_TABLE[i];
|
||||||
|
WRITE_BIT(bytes, cPos, c & MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
|
@ -772,17 +790,14 @@ unsigned int CAMBEFEC::regenerateIMBE(unsigned char* bytes) const
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CAMBEFEC::regenerate(unsigned int& a, unsigned int& b, unsigned int& c, bool b23) const
|
unsigned int CAMBEFEC::regenerateDStar(unsigned int& a, unsigned int& b) const
|
||||||
{
|
{
|
||||||
unsigned int old_a = a;
|
unsigned int orig_a = a;
|
||||||
unsigned int old_b = b;
|
unsigned int orig_b = b;
|
||||||
|
|
||||||
// For the b23 bypass
|
|
||||||
bool b24 = (b & 0x01U) == 0x01U;
|
|
||||||
|
|
||||||
unsigned int data = CGolay24128::decode24128(a);
|
unsigned int data = CGolay24128::decode24128(a);
|
||||||
|
|
||||||
unsigned int new_a = CGolay24128::encode24128(data);
|
a = CGolay24128::encode24128(data);
|
||||||
|
|
||||||
// The PRNG
|
// The PRNG
|
||||||
unsigned int p = PRNG_TABLE[data];
|
unsigned int p = PRNG_TABLE[data];
|
||||||
|
@ -791,39 +806,60 @@ unsigned int CAMBEFEC::regenerate(unsigned int& a, unsigned int& b, unsigned int
|
||||||
|
|
||||||
unsigned int datb = CGolay24128::decode24128(b);
|
unsigned int datb = CGolay24128::decode24128(b);
|
||||||
|
|
||||||
unsigned int new_b = CGolay24128::encode24128(datb);
|
b = CGolay24128::encode24128(datb);
|
||||||
|
|
||||||
new_b ^= p;
|
b ^= p;
|
||||||
|
|
||||||
if (b23) {
|
|
||||||
new_b &= 0xFFFFFEU;
|
|
||||||
new_b |= b24 ? 0x01U : 0x00U;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int errsA = 0U, errsB = 0U;
|
unsigned int errsA = 0U, errsB = 0U;
|
||||||
|
|
||||||
unsigned int v = new_a ^ old_a;
|
unsigned int v = a ^ orig_a;
|
||||||
while (v != 0U) {
|
while (v != 0U) {
|
||||||
v &= v - 1U;
|
v &= v - 1U;
|
||||||
errsA++;
|
errsA++;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = new_b ^ old_b;
|
v = b ^ orig_b;
|
||||||
while (v != 0U) {
|
while (v != 0U) {
|
||||||
v &= v - 1U;
|
v &= v - 1U;
|
||||||
errsB++;
|
errsB++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b23) {
|
return errsA + errsB;
|
||||||
if (errsA >= 4U || ((errsA + errsB) >= 6U && errsA >= 2U)) {
|
}
|
||||||
a = 0xF00292U;
|
|
||||||
b = 0x0E0B20U;
|
unsigned int CAMBEFEC::regenerateDMR(unsigned int& a, unsigned int& b) const
|
||||||
c = 0x000000U;
|
{
|
||||||
}
|
unsigned int orig_a = a;
|
||||||
|
unsigned int orig_b = b;
|
||||||
|
|
||||||
|
unsigned int data = CGolay24128::decode24128(a);
|
||||||
|
|
||||||
|
a = CGolay24128::encode24128(data);
|
||||||
|
|
||||||
|
// The PRNG
|
||||||
|
unsigned int p = PRNG_TABLE[data] >> 1;
|
||||||
|
|
||||||
|
b ^= p;
|
||||||
|
|
||||||
|
unsigned int datb = CGolay24128::decode23127(b);
|
||||||
|
|
||||||
|
b = CGolay24128::encode23127(datb) >> 1;
|
||||||
|
|
||||||
|
b ^= p;
|
||||||
|
|
||||||
|
unsigned int errsA = 0U, errsB = 0U;
|
||||||
|
|
||||||
|
unsigned int v = a ^ orig_a;
|
||||||
|
while (v != 0U) {
|
||||||
|
v &= v - 1U;
|
||||||
|
errsA++;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = new_a;
|
v = b ^ orig_b;
|
||||||
b = new_b;
|
while (v != 0U) {
|
||||||
|
v &= v - 1U;
|
||||||
|
errsB++;
|
||||||
|
}
|
||||||
|
|
||||||
return errsA + errsB;
|
return errsA + errsB;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010,2014,2016 by Jonathan Naylor G4KLX
|
* Copyright (C) 2010,2014,2016,2018 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
@ -33,7 +33,8 @@ public:
|
||||||
unsigned int regenerateIMBE(unsigned char* bytes) const;
|
unsigned int regenerateIMBE(unsigned char* bytes) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int regenerate(unsigned int& a, unsigned int& b, unsigned int& c, bool b23) const;
|
unsigned int regenerateDStar(unsigned int& a, unsigned int& b) const;
|
||||||
|
unsigned int regenerateDMR(unsigned int& a, unsigned int& b) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue