mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
129 lines
2.9 KiB
Java
129 lines
2.9 KiB
Java
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,12,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;
|
|
}
|
|
}
|