Changed NID error detection and correction (edac) to using Berlekemp Massey 63-bit block decoder for the BCH(63,16,11) code so that we can correct up to 11 bit errors in a NID (versus previous 2).

This commit is contained in:
dennis.sheirer
2015-01-04 15:29:34 +00:00
parent bb27d5cb42
commit 84261a4be9
7 changed files with 145 additions and 74 deletions

View File

@@ -220,6 +220,36 @@ public class BitSetBuffer extends BitSet
return sb.toString();
}
/**
* Returns this bitset as an array of integer ones and zeros
*/
public int[] toIntegerArray()
{
int[] values = new int[ mSize ];
for (int i = nextSetBit( 0 ); i >= 0 && i < mSize; i = nextSetBit( i+1 ) )
{
values[ i ] = 1;
}
return values;
}
/**
* Returns this bitset as a reversed bit order array of integer ones and zeros
*/
public int[] toReverseIntegerArray()
{
int[] values = new int[ mSize ];
for (int i = nextSetBit( 0 ); i >= 0 && i < mSize; i = nextSetBit( i+1 ) )
{
values[ mSize - i - 1 ] = 1;
}
return values;
}
/**
* Returns a boolean array from startIndex to end of the bitset

View File

@@ -51,6 +51,7 @@ public class LDUMessage extends P25Message
sb.append( getDUID().getLabel() );
sb.append( " LSD:" );
sb.append( getLowSpeedData() );
sb.append( " " );
return sb.toString();
}

View File

@@ -28,6 +28,7 @@ import decode.p25.message.tdu.lc.TDULinkControlMessage;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.message.tsbk.TSBKMessageFactory;
import decode.p25.reference.DataUnitID;
import edac.BCH_63_16_11;
import edac.CRC;
import edac.CRCP25;
@@ -60,6 +61,7 @@ public class P25MessageFramer implements Listener<Dibit>
private SyncPatternMatcher mMatcher;
private boolean mInverted = false;
private TrellisHalfRate mHalfRate = new TrellisHalfRate();
private BCH_63_16_11 mNIDDecoder = new BCH_63_16_11();
/**
* Constructs a C4FM message framer to receive a stream of C4FM symbols and
@@ -229,14 +231,14 @@ public class P25MessageFramer implements Listener<Dibit>
switch( mDUID )
{
case NID:
CRC crc = CRCP25.correctNID( mMessage );
CRC crc = mNIDDecoder.correctNID( mMessage );
if( crc != CRC.FAILED_CRC )
{
int value = mMessage.getInt( P25Message.DUID );
DataUnitID duid = DataUnitID.fromValue( value );
if( duid != DataUnitID.UNKN )
{
setDUID( duid );

103
src/edac/BCH_63_16_11.java Normal file
View File

@@ -0,0 +1,103 @@
package edac;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import bits.BitSetBuffer;
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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/>
******************************************************************************/
public class BCH_63_16_11 extends BerlekempMassey_63
{
private final static Logger mLog = LoggerFactory.getLogger( BCH_63_16_11.class );
/**
* BCH( 63,16,11) decoder
*/
public BCH_63_16_11()
{
/* TT = 11 = maximum correctable bit errors */
super( 11 );
}
/**
* Performs error detection and correction on the first 63 bits of the
* message argument. If the message is correctable, only the first 16 bits
* (information bits) are corrected.
*
* @return - true = success, false = failure
*/
public CRC correctNID( BitSetBuffer message )
{
CRC status = CRC.PASSED;
int[] original = message.toReverseIntegerArray();
int[] corrected = new int[ 63 ];
boolean irrecoverableErrors = decode( original, corrected );
if( irrecoverableErrors )
{
return CRC.FAILED_CRC;
}
else
{
for( int x = 0; x < 16; x++ )
{
int index = 63 - x - 1;
if( corrected[ index ] != original[ index ] )
{
status = CRC.CORRECTED;
if( corrected[ index ] == 1 )
{
message.set( x );
}
else
{
message.clear( x );
}
}
}
}
return status;
}
public static void main( String[] args )
{
String orig = "001001100000110010100101011111010001010101101001111111001010110";
String error = "010110000000110010100101011011010001011101101001101111001110110";
// xxxxxx x x x x
BitSetBuffer errorMessage = BitSetBuffer.load( error );
BCH_63_16_11 bch = new BCH_63_16_11();
mLog.debug( "ORIG:" + orig );
mLog.debug( " ERR:" + errorMessage.toString() );
mLog.debug( " " );
CRC status = bch.correctNID( errorMessage );
mLog.debug( " CRC: " + status.name() );
mLog.debug( "CORR:" + errorMessage.toString().substring( 0, 16 ) );
mLog.debug( "ORIG:" + orig );
}
}

View File

@@ -41,9 +41,12 @@ package edac;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ReedSolomon
/**
* Berlekemp Massey decoder for 63-bit primitive RS/BCH block codes
*/
public class BerlekempMassey_63
{
public final static Logger mLog = LoggerFactory.getLogger( ReedSolomon.class );
public final static Logger mLog = LoggerFactory.getLogger( BerlekempMassey_63.class );
/* Golay field size GF( 2 ** MM ) */
private static final int MM = 6;
@@ -61,7 +64,7 @@ public class ReedSolomon
int[] index_of;
int[] gg;
public ReedSolomon( int tt )
public BerlekempMassey_63( int tt )
{
TT = tt;
KK = NN - 2 * TT;

View File

@@ -29,33 +29,6 @@ public class CRCP25
{
private final static Logger mLog = LoggerFactory.getLogger( CRCP25.class );
private static final int NID_MESSAGE_START = 0;
private static final int NID_CRC_START = 16;
private static final int NID_CRC_END = 48;
/**
* Network ID and Data Unit ID checksums
*/
private static long[] NID_DUID_CHECKSUMS = new long[]
{
0xCD930BDD3B2Al, 0xAB5A8E33A6BEl, 0x983E4CC4E874l, 0x4C1F2662743Al,
0xEB9C98EC0136l, 0xB85D47AB3BB0l, 0x5C2EA3D59DD8l, 0x2E1751EACEECl,
0x170BA8F56776l, 0xC616DFA78890l, 0x630B6FD3C448l, 0x3185B7E9E224l,
0x18C2DBF4F112l, 0xC1F2662743A2l, 0xAD6A38CE9AFBl, 0x9B2617BA7657l,
0x800000000000l, 0x400000000000l, 0x200000000000l, 0x100000000000l,
0x080000000000l, 0x040000000000l, 0x020000000000l, 0x010000000000l,
0x008000000000l, 0x004000000000l, 0x002000000000l, 0x001000000000l,
0x000800000000l, 0x000400000000l, 0x000200000000l, 0x000100000000l,
0x000080000000l, 0x000040000000l, 0x000020000000l, 0x000010000000l,
0x000008000000l, 0x000004000000l, 0x000002000000l, 0x000001000000l,
0x000000800000l, 0x000000400000l, 0x000000200000l, 0x000000100000l,
0x000000080000l, 0x000000040000l, 0x000000020000l, 0x000000010000l,
0x000000008000l, 0x000000004000l, 0x000000002000l, 0x000000001000l,
0x000000000800l, 0x000000000400l, 0x000000000200l, 0x000000000100l,
0x000000000080l, 0x000000000040l, 0x000000000020l, 0x000000000010l,
0x000000000008l, 0x000000000004l, 0x000000000002l, 0x000000000001l
};
/**
* CRC-CCITT 16-bit checksums for a message length of 80 bits plus 16
* additional checksums representing CRC checksum bit errors
@@ -222,47 +195,6 @@ public class CRCP25
0x20000000l, 0x40000000l, 0x80000000l
};
/**
* Performs CRC check and corrects single-bit errors against the message.
* @param message - bitsetbuffer containing a message of at least 64 bits.
* @return - results of CRC check and/or correction attempt
*/
public static CRC correctNID( BitSetBuffer message )
{
long calculated = 0; //Starting value
/* Iterate the set bits and XOR running checksum with lookup value */
for (int i = message.nextSetBit( NID_MESSAGE_START );
i >= NID_MESSAGE_START && i < NID_CRC_START;
i = message.nextSetBit( i+1 ) )
{
calculated ^= NID_DUID_CHECKSUMS[ i - NID_MESSAGE_START ];
}
long checksum = getLongChecksum( message, NID_CRC_START, NID_CRC_END );
if( calculated == checksum )
{
return CRC.PASSED;
}
else
{
int errorLocation = getBitError( calculated ^ checksum,
NID_DUID_CHECKSUMS );
if( errorLocation >= 0 )
{
message.flip( errorLocation + NID_MESSAGE_START );
return CRC.CORRECTED;
}
}
return CRC.FAILED_CRC;
}
/**
* Performs error detection and single-bit error correction against the
* data blocks of a PDU1 message.

View File

@@ -18,7 +18,7 @@ package edac;
* along with this program. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
public class ReedSolomon_24_12_13 extends ReedSolomon
public class ReedSolomon_24_12_13 extends BerlekempMassey_63
{
/**
* Reed-Solomon RS(24,12,13) decoder