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:
168
src/edac/Golay24.java
Normal file
168
src/edac/Golay24.java
Normal file
@@ -0,0 +1,168 @@
|
||||
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 );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user