mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
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:
@@ -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
|
||||
|
||||
@@ -51,6 +51,7 @@ public class LDUMessage extends P25Message
|
||||
sb.append( getDUID().getLabel() );
|
||||
sb.append( " LSD:" );
|
||||
sb.append( getLowSpeedData() );
|
||||
sb.append( " " );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -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
103
src/edac/BCH_63_16_11.java
Normal 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 );
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user