mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
P25 audio decoder integration.
Auto-discovers the jmbe ( https://github.com/DSheirer/jmbe ) library at startup and provides decode P25 Phase 1 audio
This commit is contained in:
128
src/edac/Golay23.java
Normal file
128
src/edac/Golay23.java
Normal file
@@ -0,0 +1,128 @@
|
||||
package edac;
|
||||
|
||||
import bits.BinaryMessage;
|
||||
|
||||
public class Golay23
|
||||
{
|
||||
public static final int MAX_CORRECTABLE_ERRORS = 3;
|
||||
|
||||
public static final int[] CHECKSUMS = new int[]
|
||||
{
|
||||
0x63A, 0x31D, 0x7B4, 0x3DA, 0x1ED, 0x6CC, 0x366, 0x1B3,
|
||||
0x6E3, 0x54B, 0x49F, 0x475, 0x400, 0x200, 0x100, 0x080,
|
||||
0x040, 0x020, 0x010, 0x008, 0x004, 0x002, 0x001
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements Golay(23,11,7) error detection and correction. Returns the
|
||||
* number of detected errors. If the error count is less than or equal to
|
||||
* the max correctable errors (3), then the error bits are corrected.
|
||||
* Otherwise the message is left intact and an error count greater than 3
|
||||
* is returned.
|
||||
*
|
||||
* @param frame - message frame bitset
|
||||
* @param startIndex - first bit index of the golay protected bit sequence
|
||||
*
|
||||
* @return - number of detected errors
|
||||
*/
|
||||
public static int checkAndCorrect( BinaryMessage frame, int startIndex )
|
||||
{
|
||||
int syndrome = getSyndrome( frame, startIndex );
|
||||
|
||||
/* No errors */
|
||||
if( syndrome == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
BinaryMessage copy = frame.getSubMessage( startIndex, startIndex + 23 );
|
||||
|
||||
int index = -1;
|
||||
int syndromeWeight = MAX_CORRECTABLE_ERRORS;
|
||||
int errors = 0;
|
||||
|
||||
while( index < 23 )
|
||||
{
|
||||
if( index != -1 )
|
||||
{
|
||||
/* restore the previous flipped bit */
|
||||
if( index > 0 )
|
||||
{
|
||||
copy.flip( index - 1 );
|
||||
}
|
||||
|
||||
copy.flip( index );
|
||||
|
||||
syndromeWeight = MAX_CORRECTABLE_ERRORS - 1;
|
||||
}
|
||||
|
||||
syndrome = getSyndrome( copy, 0 );
|
||||
|
||||
if( syndrome > 0 )
|
||||
{
|
||||
for( int i = 0; i < 23; i++ )
|
||||
{
|
||||
errors = Integer.bitCount( syndrome );
|
||||
|
||||
if( errors <= syndromeWeight )
|
||||
{
|
||||
copy.xor( 12, 11, syndrome );
|
||||
|
||||
copy.rotateRight( i, 0, 22 );
|
||||
|
||||
if( index >= 0 )
|
||||
{
|
||||
errors ++;
|
||||
}
|
||||
|
||||
int corrected = copy.getInt( 0, 22 );
|
||||
int original = frame.getInt( startIndex, startIndex + 22 );
|
||||
|
||||
int errorCount = Integer.bitCount( original ^ corrected );
|
||||
|
||||
if( errorCount <= 3 )
|
||||
{
|
||||
frame.load( startIndex, 23, corrected );
|
||||
}
|
||||
|
||||
return errorCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy.rotateLeft( 0, 22 );
|
||||
syndrome = getSyndrome( copy, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return an error count greater than 3 to indicate failed correction attempt */
|
||||
return 4;
|
||||
}
|
||||
|
||||
private static int getSyndrome( BinaryMessage frame, int startIndex )
|
||||
{
|
||||
int calculated = calculateChecksum( frame, startIndex );
|
||||
|
||||
int checksum = frame.getInt( startIndex + 12, startIndex + 22 );
|
||||
|
||||
return ( checksum ^ calculated );
|
||||
}
|
||||
|
||||
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 + 12;
|
||||
i = frame.nextSetBit( i+1 ) )
|
||||
{
|
||||
calculated ^= CHECKSUMS[ i - startIndex ];
|
||||
}
|
||||
|
||||
return calculated;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user