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;
}
}