P25 - adds CRC-9 error detection to confirmed PDU message blocks

This commit is contained in:
dennis.sheirer
2015-01-18 12:43:10 +00:00
parent 35855b08bb
commit 51d6b328bd
6 changed files with 119 additions and 15 deletions

View File

@@ -114,13 +114,14 @@ public class Trellis_3_4_Rate
add( c );
}
/* The final decoded survivor path should be at index 0 */
Path path = mSurvivorPaths.get( 0 );
/* The final decoded survivor path should be at path metrics tribit 0 */
Path path = mPathMetrics.getPath( Tribit.T0 );
/* We should have a path with 50 nodes, counting the starting 000 node
* and the flushing 000 node, otherwise there was an error */
if( path != null && path.getNodes().size() == 50 )
{
mLog.debug( path.toString() );
/* Clear the original message bits */
message.clear( start, end );
@@ -237,6 +238,11 @@ public class Trellis_3_4_Rate
return 0;
}
public Path getPath( Tribit tribit )
{
return mMetrics.get( tribit );
}
/**
* Evaluates the path's metric against the current best path metric for
* the final state tribit of the path. If the path's metric is higher
@@ -424,6 +430,8 @@ public class Trellis_3_4_Rate
StringBuilder sb = new StringBuilder();
sb.append( "PATH [" );
sb.append( mNodes.size() );
sb.append( "-" );
sb.append( mPathMetric );
sb.append( "] " );
@@ -633,9 +641,8 @@ public class Trellis_3_4_Rate
*/
public static void main( String[] args )
{
String raw = "0010001000010110011110101111110101110101110111010110011100000111011001011101111011110111011001000110001000100010001011011110001000100010101101110010001000101101010010100000101000001010000010101010";
// String raw = "0010001100010110011110100111110101110101110111110110011100000111011001011101111011110111011001000110001000100010101011011110001000100010101101110010001000101101010010100000101000001010000010101010";
// x x x x
String raw = "0010001001110110000100100000101000001010000010100000101000001010000010100000101000001010000010100000101000001010000010100000101000001010000010100000001101000100011101011011000001110110000001101111";
BitSetBuffer message = BitSetBuffer.load( raw );
mLog.debug( "MSG: " + message.toString() );

View File

@@ -6,7 +6,8 @@ import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Vendor;
import edac.CRC;
import edac.CRCP25;
public class PDUConfirmedMessage extends PDUMessage
{
@@ -17,9 +18,29 @@ public class PDUConfirmedMessage extends PDUMessage
AliasList aliasList )
{
super( message, duid, aliasList );
checkCRC();
mLog.debug( toString() );
}
private void checkCRC()
{
int blocks = getBlocksToFollowCount();
/* The NID and Header have already passed CRC */
mCRC = new CRC[ 2 + blocks ];
mCRC[ 0 ] = CRC.PASSED;
mCRC[ 1 ] = CRC.PASSED;
for( int x = 0; x < getBlocksToFollowCount(); x++ )
{
/* Data blocks start at 160 and every 144 thereafter */
mCRC[ x + 2 ] = CRCP25.checkCRC9( mMessage, 160 + ( x * 144 ) );
}
//TODO: check the final 4-byte end of block sequence CRC
}
/* Override for now */
public boolean isValid()
@@ -36,6 +57,9 @@ public class PDUConfirmedMessage extends PDUMessage
sb.append( getNAC() );
sb.append( " " );
sb.append( getDUID().getLabel() );
sb.append( " CRC " );
sb.append( getErrorStatus() );
sb.append( " LLID:" );
sb.append( getLogicalLinkID() );

View File

@@ -12,7 +12,10 @@ public enum Encryption
DES_OFB( 0x81 ),
TRIPLE_DES_2_KEY( 0x82 ),
TRIPLE_DES_3_KEY( 0x83 ),
AES( 0x84 ),
AES_256( 0x84 ),
DES_XL( 0x9F ), /* Motorola Proprietary */
DVI_XL( 0xA0 ), /* Motorola Proprietary */
DVP_XL( 0xA1 ), /* Motorola Proprietary */
ADP( 0xAA ),
UNKNOWN( -1 );
@@ -46,7 +49,13 @@ public enum Encryption
case 0x83:
return TRIPLE_DES_3_KEY;
case 0x84:
return AES;
return AES_256;
case 0x9F:
return DES_OFB;
case 0xA0:
return DVI_XL;
case 0xA1:
return DVP_XL;
default:
return UNKNOWN;
}

View File

@@ -408,8 +408,8 @@ public class P25MessageFramer implements Listener<Dibit>
if( current < blocks )
{
mMessageLength += 196;
mMessage.setSize( mMessage.size() + 196 );
mMessageLength = mMessage.size();
}
else
{

View File

@@ -51,6 +51,29 @@ public class CRCP25
0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000
};
/**
* Confirmed Packet Data Unit CRC-9 checksums, generated by:
*
* long[] table = generate( 135, 9, 0x259l, 0x1FF, false, Parity.NONE );
*/
public static final int[] CRC9_CHECKSUMS = new int[]
{
0x1E7, 0x1F3, 0x1F9, 0x1FC, 0x0D2, 0x045, 0x122, 0x0BD, 0x15E, 0x083,
0x141, 0x1A0, 0x0FC, 0x052, 0x005, 0x102, 0x0AD, 0x156, 0x087, 0x143,
0x1A1, 0x1D0, 0x0C4, 0x04E, 0x00B, 0x105, 0x182, 0x0ED, 0x176, 0x097,
0x14B, 0x1A5, 0x1D2, 0x0C5, 0x162, 0x09D, 0x14E, 0x08B, 0x145, 0x1A2,
0x0FD, 0x17E, 0x093, 0x149, 0x1A4, 0x0FE, 0x053, 0x129, 0x194, 0x0E6,
0x05F, 0x12F, 0x197, 0x1CB, 0x1E5, 0x1F2, 0x0D5, 0x16A, 0x099, 0x14C,
0x08A, 0x069, 0x134, 0x0B6, 0x077, 0x13B, 0x19D, 0x1CE, 0x0CB, 0x165,
0x1B2, 0x0F5, 0x17A, 0x091, 0x148, 0x088, 0x068, 0x018, 0x020, 0x03C,
0x302, 0x035, 0x11A, 0x0A1, 0x150, 0x084, 0x06E, 0x01B, 0x10D, 0x186,
0x0EF, 0x177, 0x1BB, 0x1DD, 0x1EE, 0x0DB, 0x16D, 0x1B6, 0x0F7, 0x17B,
0x1BD, 0x1DE, 0x0C3, 0x161, 0x1B0, 0x0F4, 0x056, 0x007, 0x103, 0x181,
0x1C0, 0x0CC, 0x04A, 0x009, 0x104, 0x0AE, 0x07B, 0x13D, 0x19E, 0x0E3,
0x171, 0x1B8, 0x0F0, 0x054, 0x006, 0x02F, 0x117, 0x18B, 0x1C5, 0x1E2,
0x0DD, 0x16E, 0x09B, 0x14D, 0x1A6
};
/**
* CRC-32 checksums for PDU1 ( HEADER + 1 Block ) messages, generated by:
*
@@ -299,6 +322,40 @@ public class CRCP25
return CRC.FAILED_CRC;
}
/**
* Error detection for CRC-9 protected Confirmed Packet Data blocks. These
* data blocks have a slightly complicated structure because the checksum
* is located between bits 7-15, within a 144 bit block. The checksums
* were generated assuming that the message is contiguous from 0 - 134 bits.
* No data correction is performed.
*/
public static CRC checkCRC9( BitSetBuffer message, int messageStart )
{
int calculated = 0x1FF; //Initial fill of all ones
/* Iterate the set bits and XOR running checksum with lookup value */
for (int i = message.nextSetBit( messageStart );
i >= messageStart && i < messageStart + 144;
i = message.nextSetBit( i+1 ) )
{
/* message bits before the CRC */
if( i < ( messageStart + 7 ) )
{
calculated ^= CRC9_CHECKSUMS[ i - messageStart ];
}
/* message bits after the CRC */
else if( i > ( messageStart + 15 ) )
{
calculated ^= CRC9_CHECKSUMS[ i - messageStart - 9 ];
}
}
int checksum = message.getInt( messageStart + 7, messageStart + 15 );
return ( calculated ^ checksum ) == 0 ? CRC.PASSED : CRC.FAILED_CRC;
}
/**
* Performs Galois 24/12/7 error detection and correction against the 12
@@ -375,13 +432,13 @@ public class CRCP25
public static void main( String[] args )
{
String raw = "0010011000001100101001010111110100010101011010011111110010101100001101111111110100000000000000000001001001101001100000010011101000000000000000001000110101001000000000010010011100111111111000110011110000111000011100000000000000001001111001000101101100001010";
String raw = "000000010110100101010001000000000100010100000000000000000010000000011001001011100000000000000000011111110001000101001011100101110000101000110011";
BitSetBuffer message = BitSetBuffer.load( raw );
mLog.debug( "MSG:" + message.toString() );
CRC results = correctPDU1( message );
CRC results = checkCRC9( message, 0 );
mLog.debug( "COR:" + message.toString() );

View File

@@ -153,10 +153,17 @@ public class CRCUtil
public static void main( String[] args )
{
mLog.debug( "Starting" );
long polynomial = 0xC75l;
long[] table = generate( 12, 11, polynomial, 0x0, true, Parity.NONE );
// String raw = "000000001010001000000000100010100000000000000000010000000011001001011100000000000000000011111110001000101001011100101110000101000110011101101001";
// BitSetBuffer message = BitSetBuffer.load( raw );
//
// long polynomial = 0x259l;
//
// decode( message, 0, 135, polynomial, 9 );
//
// mLog.debug( message.toString() );
long[] table = generate( 135, 9, 0x259l, 0, false, Parity.NONE );
mLog.debug( toCodeArray( table ) );
mLog.debug( "Finished" );
}