Initial commit of redesigned internal processing and audio management.

Note: Several of the decoders are currently non-functioning in this
commit.  If you want the latest functioning codebase, please checkout
the commit prior to this one.  All decoders will eventually be updated
with this new architecture.

Currently broken:
- Logging and recording
- Aux decoders (Fleetsync/MDC/LoJack/Tait)
- LTR/Passport decoders

Changes in this commit:
- Module architecture for decoders and components with central
provisioning by the DecoderFactory
- Transition from Complex sample stream processing to float buffer
processing for improved memory management
- Redesigned filter structures - to support buffers and streams
- Resolved several memory leak issues
- Universal sharing of the thread pool manager
- Added centralized audio management with call/user prioritization and
new gui with mute/volume controls
- Embedded audio metadata for eventual streaming support
- Redesigned ProcessingChain to support independent re-use
- Added new TrafficChannelManager to handle traffic channel allocations
- Traffic Channel pool size and Call timeout available in P25 and
MPT1327 configs
- Redesigned channel and decoder gui components
This commit is contained in:
denny
2015-09-01 07:10:26 -04:00
parent 538a299246
commit f4d8ea281d
570 changed files with 21578 additions and 17012 deletions

View File

@@ -0,0 +1,284 @@
package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.P25Message;
import module.decode.p25.message.tsbk.motorola.MotorolaOpcode;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.LinkControlOpcode;
import module.decode.p25.reference.Vendor;
import module.decode.p25.reference.VendorLinkControlOpcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRC;
import edac.Golay24;
import edac.ReedSolomon_63_47_17;
public class TDULinkControlMessage extends P25Message
{
public final static Logger mLog = LoggerFactory.getLogger( TDULinkControlMessage.class );
public static final int[] LC_HEX_0 = { 64,65,66,67,68,69 };
public static final int[] LC_HEX_1 = { 70,71,72,73,74,75 };
public static final int[] LC_HEX_2 = { 88,89,90,91,92,93 };
public static final int[] LC_HEX_3 = { 94,95,96,97,98,99 };
public static final int[] LC_HEX_4 = { 112,113,114,115,116,117 };
public static final int[] LC_HEX_5 = { 118,119,120,121,122,123 };
public static final int[] LC_HEX_6 = { 136,137,138,139,140,141 };
public static final int[] LC_HEX_7 = { 142,143,144,145,146,147 };
public static final int[] LC_HEX_8 = { 160,161,162,163,164,165 };
public static final int[] LC_HEX_9 = { 166,167,168,169,170,171 };
public static final int[] LC_HEX_10 = { 184,185,186,187,188,189 };
public static final int[] LC_HEX_11 = { 190,191,192,193,194,195 };
public static final int[] RS_HEX_0 = { 208,209,210,211,212,213 };
public static final int[] RS_HEX_1 = { 214,215,216,217,218,219 };
public static final int[] RS_HEX_2 = { 232,233,234,235,236,237 };
public static final int[] RS_HEX_3 = { 238,239,240,241,242,243 };
public static final int[] RS_HEX_4 = { 256,257,258,259,260,261 };
public static final int[] RS_HEX_5 = { 262,263,264,265,266,267 };
public static final int[] RS_HEX_6 = { 280,281,282,283,284,285 };
public static final int[] RS_HEX_7 = { 286,287,288,289,290,291 };
public static final int[] RS_HEX_8 = { 304,305,306,307,308,309 };
public static final int[] RS_HEX_9 = { 310,311,312,313,314,315 };
public static final int[] RS_HEX_10 = { 328,329,330,331,332,333 };
public static final int[] RS_HEX_11 = { 334,335,336,337,338,339 };
public static final int ENCRYPTION_FLAG = 64;
public static final int IMPLICIT_VENDOR_FLAG = 65;
public static final int[] OPCODE = { 66,67,68,69,70,71 };
public static final int[] VENDOR = { 72,73,74,75,88,89,90,91 };
/* Reed-Solomon(24,12,13) code protects the link control word. Maximum
* correctable errors are: Hamming Distance(13) / 2 = 6 */
public static final ReedSolomon_63_47_17 mReedSolomonDecoder =
new ReedSolomon_63_47_17( 6 );
public TDULinkControlMessage( BinaryMessage message, DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
/* NID CRC is checked in the message framer so a constructed message
* means it passed the CRC */
mCRC = new CRC[ 3 ];
mCRC[ 0 ] = CRC.PASSED;
checkCRC();
}
/**
* Constructs a TDULinkControl message from an existing message and bypasses
* the CRC calculation.
*/
protected TDULinkControlMessage( TDULinkControlMessage message )
{
super( message.getSourceMessage(), DataUnitID.TDULC, message.getAliasList() );
mCRC = message.getCRC();
}
public CRC[] getCRC()
{
return mCRC;
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " " );
sb.append( mMessage.toString() );
return sb.toString();
}
public String getMessageStub()
{
StringBuilder sb = new StringBuilder();
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " " );
sb.append( getDUID().getLabel() );
sb.append( " " );
if( isEncrypted() )
{
sb.append( "ENCRYPTED" );
}
else
{
if( isImplicitFormat() || getVendor() == Vendor.STANDARD )
{
sb.append( getOpcode().getLabel() );
}
else
{
sb.append( "VENDOR:" + getVendor().getLabel() + " " );
sb.append( getVendorOpcode().getLabel() );
}
}
return sb.toString();
}
public boolean isEncrypted()
{
return mMessage.get( ENCRYPTION_FLAG );
}
public boolean isImplicitFormat()
{
return mMessage.get( IMPLICIT_VENDOR_FLAG );
}
/**
* Standard opcodes when the Vendor is STANDARD
*/
public LinkControlOpcode getOpcode()
{
return LinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
}
/**
* Returns a generic vendor-neutral opcode. Use this when there is a non
* standard vendor code.
*/
public VendorLinkControlOpcode getVendorOpcode()
{
return VendorLinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
}
/**
* If the vendor is motorola, returns the Motorola OPCODE for this message
*/
public MotorolaOpcode getMotorolaOpcode()
{
return MotorolaOpcode.fromValue( mMessage.getInt( OPCODE ) );
}
public Vendor getVendor()
{
if( isImplicitFormat() )
{
return Vendor.STANDARD;
}
return Vendor.fromValue( mMessage.getInt( VENDOR ) );
}
/**
* Checks and repairs the 12 x 24-bit golay(24,12,8) codewords and then
* checks and repairs the 24 x 6-bit link control and reed-solomon
* RS(24,12,13) parity codewords
*/
private void checkCRC()
{
/* Check the Golay codewords */
int x = 64;
mCRC[ 1 ] = CRC.PASSED;
while( x < mMessage.size() )
{
mMessage = Golay24.checkAndCorrect( mMessage, x );
if( !( mMessage.getCRC() == CRC.PASSED ) )
{
mCRC[ 1 ] = CRC.FAILED_CRC;
}
x += 24;
}
/* Check the Reed-Solomon parity bits. The RS decoder expects the link
* control data and reed solomon parity hex codewords in reverse order.
* The RS(24,12,13) code used by P25 removes the left-hand 47 data hex
* words, so we replace them with zeros. */
int[] input = new int [63];
int[] output = new int [63];
input[ 0 ] = mMessage.getInt( RS_HEX_11 );
input[ 1 ] = mMessage.getInt( RS_HEX_10 );
input[ 2 ] = mMessage.getInt( RS_HEX_9 );
input[ 3 ] = mMessage.getInt( RS_HEX_8 );
input[ 4 ] = mMessage.getInt( RS_HEX_7 );
input[ 5 ] = mMessage.getInt( RS_HEX_6 );
input[ 6 ] = mMessage.getInt( RS_HEX_5 );
input[ 7 ] = mMessage.getInt( RS_HEX_4 );
input[ 8 ] = mMessage.getInt( RS_HEX_3 );
input[ 9 ] = mMessage.getInt( RS_HEX_2 );
input[ 10 ] = mMessage.getInt( RS_HEX_1 );
input[ 11 ] = mMessage.getInt( RS_HEX_0 );
input[ 12 ] = mMessage.getInt( LC_HEX_11 );
input[ 13 ] = mMessage.getInt( LC_HEX_10 );
input[ 14 ] = mMessage.getInt( LC_HEX_9 );
input[ 15 ] = mMessage.getInt( LC_HEX_8 );
input[ 16 ] = mMessage.getInt( LC_HEX_7 );
input[ 17 ] = mMessage.getInt( LC_HEX_6 );
input[ 18 ] = mMessage.getInt( LC_HEX_5 );
input[ 19 ] = mMessage.getInt( LC_HEX_4 );
input[ 20 ] = mMessage.getInt( LC_HEX_3 );
input[ 21 ] = mMessage.getInt( LC_HEX_2 );
input[ 22 ] = mMessage.getInt( LC_HEX_1 );
input[ 23 ] = mMessage.getInt( LC_HEX_0 );
/* indexes 24 - 62 are defaulted to zero */
boolean irrecoverableErrors = mReedSolomonDecoder.decode( input, output );
if( irrecoverableErrors )
{
mCRC[ 2 ] = CRC.FAILED_CRC;
}
else
{
mCRC[ 2 ] = CRC.PASSED;
/* Only fix the link control data hex codewords */
repairHexCodeword( input, output, 12, LC_HEX_11 );
repairHexCodeword( input, output, 13, LC_HEX_10 );
repairHexCodeword( input, output, 14, LC_HEX_9 );
repairHexCodeword( input, output, 15, LC_HEX_8 );
repairHexCodeword( input, output, 16, LC_HEX_7 );
repairHexCodeword( input, output, 17, LC_HEX_6 );
repairHexCodeword( input, output, 18, LC_HEX_5 );
repairHexCodeword( input, output, 19, LC_HEX_4 );
repairHexCodeword( input, output, 20, LC_HEX_3 );
repairHexCodeword( input, output, 21, LC_HEX_2 );
repairHexCodeword( input, output, 22, LC_HEX_1 );
repairHexCodeword( input, output, 23, LC_HEX_0 );
/* If the golay check failed, mark it as corrected too */
if( mCRC[ 1 ] == CRC.FAILED_CRC )
{
mCRC[ 1 ] = CRC.CORRECTED;
}
}
}
private void repairHexCodeword( int[] input, int[] output, int index, int[] indexSet )
{
if( input[ index ] != output[ index ] )
{
mMessage.load( indexSet[ 0 ], 6, output[ index ] );
mCRC[ 2 ] = CRC.CORRECTED;
}
}
/**
* Indicates if the message passed the golay and reed-solomon parity checks
* or was corrected.
*/
public boolean isValid()
{
// mCRC[ 0 ] - always passes (otherwise message wouldn't be constructed )
// mCRC[ 1 ] - golay - always passes or corrected if mCRC[2] is valid
return mCRC[ 2 ] == CRC.PASSED || mCRC[ 2 ] == CRC.CORRECTED;
}
}