mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Auto-discovers the jmbe ( https://github.com/DSheirer/jmbe ) library at startup and provides decode P25 Phase 1 audio
169 lines
4.2 KiB
Java
169 lines
4.2 KiB
Java
package edac;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import bits.BinaryMessage;
|
|
|
|
/*******************************************************************************
|
|
* SDR Trunk
|
|
* Copyright (C) 2014 Dennis Sheirer
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
* -----------------------------------------------------------------------
|
|
* Galois24 decoder based on Hank Wallace's tutorial/algorithm located at:
|
|
* http://www.aqdi.com/golay.htm
|
|
******************************************************************************/
|
|
|
|
/**
|
|
* Galois 24/12/7 decoder
|
|
*/
|
|
public class Golay24
|
|
{
|
|
private final static Logger mLog = LoggerFactory.getLogger( Golay24.class );
|
|
|
|
/**
|
|
* Galois 24/12 checksums generated by:
|
|
*
|
|
* CRCUtil.generate( 12, 11, 0xC75, 0x0, true );
|
|
*/
|
|
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
|
|
};
|
|
|
|
private static int calculateChecksum( BinaryMessage message, int startIndex )
|
|
{
|
|
int calculated = 0; //Starting value
|
|
|
|
/* Iterate the set bits and XOR running checksum with lookup value */
|
|
for (int i = message.nextSetBit( startIndex );
|
|
i >= startIndex && i < startIndex + 12;
|
|
i = message.nextSetBit( i+1 ) )
|
|
{
|
|
calculated ^= CHECKSUMS[ i - startIndex ];
|
|
}
|
|
|
|
return calculated;
|
|
}
|
|
|
|
/**
|
|
* Performs error detection and returns a corrected copy of the 24-bit
|
|
* message that starts at the start index.
|
|
* @param message - source message containing startIndex + 24 bits length
|
|
* @param startIndex - start of the 24-bit galois 24 protected bit set
|
|
* @return - corrected 24-bit galois value
|
|
*/
|
|
public static BinaryMessage checkAndCorrect( BinaryMessage message, int startIndex )
|
|
{
|
|
boolean parityError = message.cardinality() % 2 != 0;
|
|
|
|
int syndrome = getSyndrome( message, startIndex );
|
|
|
|
/* No errors */
|
|
if( syndrome == 0 )
|
|
{
|
|
if( parityError )
|
|
{
|
|
message.flip( startIndex + 23 );
|
|
}
|
|
|
|
message.setCRC( CRC.PASSED );
|
|
|
|
return message;
|
|
}
|
|
|
|
/* Get original message value */
|
|
int original = message.getInt( 0, 22 );
|
|
|
|
int index = -1;
|
|
int syndromeWeight = 3;
|
|
int errors = 0;
|
|
|
|
while( index < 23 )
|
|
{
|
|
if( index != -1 )
|
|
{
|
|
/* restore the previous flipped bit */
|
|
if( index > 0 )
|
|
{
|
|
message.flip( index - 1 );
|
|
}
|
|
|
|
message.flip( index );
|
|
|
|
syndromeWeight = 2;
|
|
}
|
|
|
|
syndrome = getSyndrome( message, startIndex );
|
|
|
|
if( syndrome > 0 )
|
|
{
|
|
for( int i = 0; i < 23; i++ )
|
|
{
|
|
|
|
errors = Integer.bitCount( syndrome );
|
|
|
|
if( errors <= syndromeWeight )
|
|
{
|
|
message.xor( 12, 11, syndrome );
|
|
|
|
message.rotateRight( i, startIndex, startIndex + 22 );
|
|
|
|
if( index >= 0 )
|
|
{
|
|
errors ++;
|
|
}
|
|
|
|
int corrected = message.getInt( 0, 22 );
|
|
|
|
if( Integer.bitCount( original ^ corrected ) > 3 )
|
|
{
|
|
message.setCRC( CRC.FAILED_CRC );
|
|
|
|
return message;
|
|
}
|
|
|
|
message.setCRC( CRC.PASSED );
|
|
|
|
return message;
|
|
}
|
|
else
|
|
{
|
|
message.rotateLeft( startIndex, startIndex + 22 );
|
|
syndrome = getSyndrome( message, startIndex );
|
|
}
|
|
}
|
|
|
|
index++;
|
|
}
|
|
}
|
|
|
|
message.setCRC( CRC.FAILED_CRC );
|
|
|
|
return message;
|
|
}
|
|
|
|
private static int getSyndrome( BinaryMessage message, int startIndex )
|
|
{
|
|
int calculated = calculateChecksum( message, startIndex );
|
|
|
|
int checksum = message.getInt( startIndex + 12, startIndex + 22 );
|
|
|
|
return ( checksum ^ calculated );
|
|
}
|
|
}
|