mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
P25 - adds CRC-9 error detection to confirmed PDU message blocks
This commit is contained in:
@@ -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() );
|
||||
|
||||
@@ -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() );
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -408,8 +408,8 @@ public class P25MessageFramer implements Listener<Dibit>
|
||||
|
||||
if( current < blocks )
|
||||
{
|
||||
mMessageLength += 196;
|
||||
mMessage.setSize( mMessage.size() + 196 );
|
||||
mMessageLength = mMessage.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -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() );
|
||||
|
||||
|
||||
@@ -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" );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user