mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
#1633 DMR Decoder redesign. Uses new DQPSK vector/scalar demodulator implementations and soft sync detectors for more accurate detections and symbol timing and symbol period calculations. Includes two new calibrations with scalar and vector implementations for DQPSK demodulator and Interpolator. Enhances DMR error detection and correction algorithms, specifically the block product turbo code algorithms. (#2115)
Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
@@ -1,13 +1,63 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.edac;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
|
||||
/**
|
||||
* Hamming(16,11,5) Error detection and correction utility.
|
||||
* Hamming(16,11,4) Error detection and correction utility. This code is capable of correcting single-bit errors and
|
||||
* detecting (but not correcting) double-bit errors.
|
||||
*/
|
||||
public class Hamming16
|
||||
public class Hamming16 implements IHamming
|
||||
{
|
||||
private static int[] CHECKSUMS = new int[]{0x13, 0x1A, 0x1F, 0x1C, 0x0E, 0x15, 0x0B, 0x16, 0x19, 0x0D, 0x07};
|
||||
private static int[] CHECKSUMS = new int[]{0x13, 0x1A, 0x1F, 0x1C, 0x0E, 0x15, 0x0B, 0x16, 0x19, 0x0D, 0x07, 0x10,
|
||||
0x08, 0x04, 0x02, 0x01};
|
||||
|
||||
/**
|
||||
* Calculates the bit error index of the Hamming(16,11,4) protected word that is contained in the binary message
|
||||
* starting at the specified offset.
|
||||
*
|
||||
* @param message containing a Hamming protected word
|
||||
* @param offset to the start of the protected word
|
||||
* @return message index for an error bit or -1 if no errors are detected or 1000 if two bit errors are detected.
|
||||
*/
|
||||
public int getErrorIndex(BinaryMessage message, int offset)
|
||||
{
|
||||
int syndrome = getSyndrome(message, offset);
|
||||
|
||||
if(syndrome == 0)
|
||||
{
|
||||
return NO_ERRORS;
|
||||
}
|
||||
|
||||
for(int index = 0; index < CHECKSUMS.length; index++)
|
||||
{
|
||||
if(syndrome == CHECKSUMS[index])
|
||||
{
|
||||
return index + offset;
|
||||
}
|
||||
}
|
||||
|
||||
return MULTIPLE_ERRORS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs error detection and correction of any single-bit errors and detection of any double-bit errors (SECDED)
|
||||
@@ -22,78 +72,36 @@ public class Hamming16
|
||||
{
|
||||
int syndrome = getSyndrome(frame, startIndex);
|
||||
|
||||
switch(syndrome)
|
||||
if (syndrome == 0)
|
||||
{
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
frame.flip(startIndex + 15); //Parity 1
|
||||
return 1;
|
||||
case 2:
|
||||
frame.flip(startIndex + 14); //Parity 2
|
||||
return 1;
|
||||
case 3:
|
||||
frame.flip(startIndex + 10); //Data 1
|
||||
return 1;
|
||||
case 4:
|
||||
frame.flip(startIndex + 13); //Parity 4
|
||||
return 1;
|
||||
case 5:
|
||||
frame.flip(startIndex + 9); //Data 2
|
||||
return 1;
|
||||
case 6:
|
||||
frame.flip(startIndex + 8); //Data 3
|
||||
return 1;
|
||||
case 7:
|
||||
frame.flip(startIndex + 7); //Data 4
|
||||
return 1;
|
||||
case 8:
|
||||
frame.flip(startIndex + 12); //Parity 8
|
||||
return 1;
|
||||
case 9:
|
||||
frame.flip(startIndex + 6); //Data 5
|
||||
return 1;
|
||||
case 10:
|
||||
frame.flip(startIndex + 5); //Data 6
|
||||
return 1;
|
||||
case 11:
|
||||
frame.flip(startIndex + 4); //Data 7
|
||||
return 1;
|
||||
case 12:
|
||||
frame.flip(startIndex + 3); //Data 8
|
||||
return 1;
|
||||
case 13:
|
||||
frame.flip(startIndex + 2); //Data 9
|
||||
return 1;
|
||||
case 14:
|
||||
frame.flip(startIndex + 1); //Data 10
|
||||
return 1;
|
||||
case 15:
|
||||
frame.flip(startIndex); //Data 11
|
||||
return 1;
|
||||
case 16:
|
||||
frame.flip(startIndex + 11); //Parity 16
|
||||
return 1;
|
||||
default:
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int index = 0; index < CHECKSUMS.length; index++)
|
||||
{
|
||||
if(CHECKSUMS[index] == syndrome)
|
||||
{
|
||||
frame.flip(startIndex + index);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the checksum (Parity 16,8,4,2,1) for data (11 <> 1 ) bits.
|
||||
* Calculates the checksum from the transmitted data bits.
|
||||
*
|
||||
* @param frame - frame containing hamming protected word
|
||||
* @param startIndex - start bit index of the hamming protected word
|
||||
* @return parity value, 0 - 16
|
||||
* @return calculated checksum value
|
||||
*/
|
||||
private static int calculateChecksum(BinaryMessage frame, int startIndex)
|
||||
{
|
||||
int calculated = 0; //Starting value
|
||||
|
||||
/* Iterate the set bits and XOR running checksum with lookup value */
|
||||
for(int i = frame.nextSetBit(startIndex);
|
||||
i >= startIndex && i < startIndex + 11;
|
||||
i = frame.nextSetBit(i + 1))
|
||||
for(int i = frame.nextSetBit(startIndex); i >= startIndex && i < startIndex + 11; i = frame.nextSetBit(i + 1))
|
||||
{
|
||||
calculated ^= CHECKSUMS[i - startIndex];
|
||||
}
|
||||
@@ -109,12 +117,10 @@ public class Hamming16
|
||||
* @param startIndex - of bit 0 of the hamming protected word
|
||||
* @return - 0 (no errors) or 1 (single bit error corrected)
|
||||
*/
|
||||
private static int getSyndrome(BinaryMessage frame, int startIndex)
|
||||
public static int getSyndrome(BinaryMessage frame, int startIndex)
|
||||
{
|
||||
int calculated = calculateChecksum(frame, startIndex);
|
||||
|
||||
int checksum = frame.getInt(startIndex + 11, startIndex + 15);
|
||||
|
||||
return (checksum ^ calculated);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user