diff --git a/src/bits/BitSetBuffer.java b/src/bits/BitSetBuffer.java index 75149e84..2d0b6cb2 100644 --- a/src/bits/BitSetBuffer.java +++ b/src/bits/BitSetBuffer.java @@ -220,6 +220,36 @@ public class BitSetBuffer extends BitSet return sb.toString(); } + + /** + * Returns this bitset as an array of integer ones and zeros + */ + public int[] toIntegerArray() + { + int[] values = new int[ mSize ]; + + for (int i = nextSetBit( 0 ); i >= 0 && i < mSize; i = nextSetBit( i+1 ) ) + { + values[ i ] = 1; + } + + return values; + } + + /** + * Returns this bitset as a reversed bit order array of integer ones and zeros + */ + public int[] toReverseIntegerArray() + { + int[] values = new int[ mSize ]; + + for (int i = nextSetBit( 0 ); i >= 0 && i < mSize; i = nextSetBit( i+1 ) ) + { + values[ mSize - i - 1 ] = 1; + } + + return values; + } /** * Returns a boolean array from startIndex to end of the bitset diff --git a/src/decode/p25/message/ldu/LDUMessage.java b/src/decode/p25/message/ldu/LDUMessage.java index 88501d89..2941ca91 100644 --- a/src/decode/p25/message/ldu/LDUMessage.java +++ b/src/decode/p25/message/ldu/LDUMessage.java @@ -51,6 +51,7 @@ public class LDUMessage extends P25Message sb.append( getDUID().getLabel() ); sb.append( " LSD:" ); sb.append( getLowSpeedData() ); + sb.append( " " ); return sb.toString(); } diff --git a/src/dsp/fsk/P25MessageFramer.java b/src/dsp/fsk/P25MessageFramer.java index 0e54d66d..2a02840b 100644 --- a/src/dsp/fsk/P25MessageFramer.java +++ b/src/dsp/fsk/P25MessageFramer.java @@ -28,6 +28,7 @@ import decode.p25.message.tdu.lc.TDULinkControlMessage; import decode.p25.message.tsbk.TSBKMessage; import decode.p25.message.tsbk.TSBKMessageFactory; import decode.p25.reference.DataUnitID; +import edac.BCH_63_16_11; import edac.CRC; import edac.CRCP25; @@ -60,6 +61,7 @@ public class P25MessageFramer implements Listener private SyncPatternMatcher mMatcher; private boolean mInverted = false; private TrellisHalfRate mHalfRate = new TrellisHalfRate(); + private BCH_63_16_11 mNIDDecoder = new BCH_63_16_11(); /** * Constructs a C4FM message framer to receive a stream of C4FM symbols and @@ -229,14 +231,14 @@ public class P25MessageFramer implements Listener switch( mDUID ) { case NID: - CRC crc = CRCP25.correctNID( mMessage ); + CRC crc = mNIDDecoder.correctNID( mMessage ); if( crc != CRC.FAILED_CRC ) { int value = mMessage.getInt( P25Message.DUID ); DataUnitID duid = DataUnitID.fromValue( value ); - + if( duid != DataUnitID.UNKN ) { setDUID( duid ); diff --git a/src/edac/BCH_63_16_11.java b/src/edac/BCH_63_16_11.java new file mode 100644 index 00000000..122cb5d5 --- /dev/null +++ b/src/edac/BCH_63_16_11.java @@ -0,0 +1,103 @@ +package edac; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import bits.BitSetBuffer; + +/******************************************************************************* + * 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 + ******************************************************************************/ + +public class BCH_63_16_11 extends BerlekempMassey_63 +{ + private final static Logger mLog = LoggerFactory.getLogger( BCH_63_16_11.class ); + + /** + * BCH( 63,16,11) decoder + */ + public BCH_63_16_11() + { + /* TT = 11 = maximum correctable bit errors */ + super( 11 ); + } + + /** + * Performs error detection and correction on the first 63 bits of the + * message argument. If the message is correctable, only the first 16 bits + * (information bits) are corrected. + * + * @return - true = success, false = failure + */ + public CRC correctNID( BitSetBuffer message ) + { + CRC status = CRC.PASSED; + + int[] original = message.toReverseIntegerArray(); + int[] corrected = new int[ 63 ]; + + boolean irrecoverableErrors = decode( original, corrected ); + + if( irrecoverableErrors ) + { + return CRC.FAILED_CRC; + } + else + { + for( int x = 0; x < 16; x++ ) + { + int index = 63 - x - 1; + + if( corrected[ index ] != original[ index ] ) + { + status = CRC.CORRECTED; + + if( corrected[ index ] == 1 ) + { + message.set( x ); + } + else + { + message.clear( x ); + } + } + } + } + + return status; + } + + public static void main( String[] args ) + { + String orig = "001001100000110010100101011111010001010101101001111111001010110"; + String error = "010110000000110010100101011011010001011101101001101111001110110"; +// xxxxxx x x x x + BitSetBuffer errorMessage = BitSetBuffer.load( error ); + + BCH_63_16_11 bch = new BCH_63_16_11(); + + mLog.debug( "ORIG:" + orig ); + mLog.debug( " ERR:" + errorMessage.toString() ); + mLog.debug( " " ); + + CRC status = bch.correctNID( errorMessage ); + + mLog.debug( " CRC: " + status.name() ); + mLog.debug( "CORR:" + errorMessage.toString().substring( 0, 16 ) ); + mLog.debug( "ORIG:" + orig ); + } +} diff --git a/src/edac/ReedSolomon.java b/src/edac/BerlekempMassey_63.java similarity index 98% rename from src/edac/ReedSolomon.java rename to src/edac/BerlekempMassey_63.java index f37628f7..cf7b4631 100644 --- a/src/edac/ReedSolomon.java +++ b/src/edac/BerlekempMassey_63.java @@ -41,9 +41,12 @@ package edac; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class ReedSolomon +/** + * Berlekemp Massey decoder for 63-bit primitive RS/BCH block codes + */ +public class BerlekempMassey_63 { - public final static Logger mLog = LoggerFactory.getLogger( ReedSolomon.class ); + public final static Logger mLog = LoggerFactory.getLogger( BerlekempMassey_63.class ); /* Golay field size GF( 2 ** MM ) */ private static final int MM = 6; @@ -61,7 +64,7 @@ public class ReedSolomon int[] index_of; int[] gg; - public ReedSolomon( int tt ) + public BerlekempMassey_63( int tt ) { TT = tt; KK = NN - 2 * TT; diff --git a/src/edac/CRCP25.java b/src/edac/CRCP25.java index 913ee651..72e07981 100644 --- a/src/edac/CRCP25.java +++ b/src/edac/CRCP25.java @@ -29,33 +29,6 @@ public class CRCP25 { private final static Logger mLog = LoggerFactory.getLogger( CRCP25.class ); - private static final int NID_MESSAGE_START = 0; - private static final int NID_CRC_START = 16; - private static final int NID_CRC_END = 48; - - /** - * Network ID and Data Unit ID checksums - */ - private static long[] NID_DUID_CHECKSUMS = new long[] - { - 0xCD930BDD3B2Al, 0xAB5A8E33A6BEl, 0x983E4CC4E874l, 0x4C1F2662743Al, - 0xEB9C98EC0136l, 0xB85D47AB3BB0l, 0x5C2EA3D59DD8l, 0x2E1751EACEECl, - 0x170BA8F56776l, 0xC616DFA78890l, 0x630B6FD3C448l, 0x3185B7E9E224l, - 0x18C2DBF4F112l, 0xC1F2662743A2l, 0xAD6A38CE9AFBl, 0x9B2617BA7657l, - 0x800000000000l, 0x400000000000l, 0x200000000000l, 0x100000000000l, - 0x080000000000l, 0x040000000000l, 0x020000000000l, 0x010000000000l, - 0x008000000000l, 0x004000000000l, 0x002000000000l, 0x001000000000l, - 0x000800000000l, 0x000400000000l, 0x000200000000l, 0x000100000000l, - 0x000080000000l, 0x000040000000l, 0x000020000000l, 0x000010000000l, - 0x000008000000l, 0x000004000000l, 0x000002000000l, 0x000001000000l, - 0x000000800000l, 0x000000400000l, 0x000000200000l, 0x000000100000l, - 0x000000080000l, 0x000000040000l, 0x000000020000l, 0x000000010000l, - 0x000000008000l, 0x000000004000l, 0x000000002000l, 0x000000001000l, - 0x000000000800l, 0x000000000400l, 0x000000000200l, 0x000000000100l, - 0x000000000080l, 0x000000000040l, 0x000000000020l, 0x000000000010l, - 0x000000000008l, 0x000000000004l, 0x000000000002l, 0x000000000001l - }; - /** * CRC-CCITT 16-bit checksums for a message length of 80 bits plus 16 * additional checksums representing CRC checksum bit errors @@ -222,47 +195,6 @@ public class CRCP25 0x20000000l, 0x40000000l, 0x80000000l }; - - - /** - * Performs CRC check and corrects single-bit errors against the message. - * @param message - bitsetbuffer containing a message of at least 64 bits. - * @return - results of CRC check and/or correction attempt - */ - public static CRC correctNID( BitSetBuffer message ) - { - long calculated = 0; //Starting value - - /* Iterate the set bits and XOR running checksum with lookup value */ - for (int i = message.nextSetBit( NID_MESSAGE_START ); - i >= NID_MESSAGE_START && i < NID_CRC_START; - i = message.nextSetBit( i+1 ) ) - { - calculated ^= NID_DUID_CHECKSUMS[ i - NID_MESSAGE_START ]; - } - - long checksum = getLongChecksum( message, NID_CRC_START, NID_CRC_END ); - - if( calculated == checksum ) - { - return CRC.PASSED; - } - else - { - int errorLocation = getBitError( calculated ^ checksum, - NID_DUID_CHECKSUMS ); - - if( errorLocation >= 0 ) - { - message.flip( errorLocation + NID_MESSAGE_START ); - - return CRC.CORRECTED; - } - } - - return CRC.FAILED_CRC; - } - /** * Performs error detection and single-bit error correction against the * data blocks of a PDU1 message. diff --git a/src/edac/ReedSolomon_24_12_13.java b/src/edac/ReedSolomon_24_12_13.java index 00da4573..28af356f 100644 --- a/src/edac/ReedSolomon_24_12_13.java +++ b/src/edac/ReedSolomon_24_12_13.java @@ -18,7 +18,7 @@ package edac; * along with this program. If not, see ******************************************************************************/ -public class ReedSolomon_24_12_13 extends ReedSolomon +public class ReedSolomon_24_12_13 extends BerlekempMassey_63 { /** * Reed-Solomon RS(24,12,13) decoder