mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
P25 Work in progress. Adds CRC checking to NID/DUID. Adds limiter to trellis decoder to prevent it from decoding an excessive error message. Updates channel state with initial handling/generation of call events.
This commit is contained in:
@@ -58,7 +58,7 @@ public class BaseNode extends DefaultMutableTreeNode
|
||||
return null;
|
||||
}
|
||||
|
||||
public Color getForegroundColor()
|
||||
public Color getBackgroundColor()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -54,11 +54,32 @@ public class ControllerTreeCellRenderer extends DefaultTreeCellRenderer
|
||||
|
||||
setIcon( icon );
|
||||
|
||||
Color foreground = node.getForegroundColor();
|
||||
Color background = node.getBackgroundColor();
|
||||
|
||||
if( foreground != null )
|
||||
if( background != null )
|
||||
{
|
||||
setForeground( foreground );
|
||||
setBackground( background );
|
||||
setOpaque( true );
|
||||
|
||||
if( selected )
|
||||
{
|
||||
if( background == Color.CYAN )
|
||||
{
|
||||
setForeground( Color.ORANGE );
|
||||
}
|
||||
else if( background == Color.GREEN )
|
||||
{
|
||||
setForeground( Color.MAGENTA );
|
||||
}
|
||||
else if( background == Color.RED )
|
||||
{
|
||||
setForeground( Color.YELLOW );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setOpaque( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ public abstract class CallEvent
|
||||
|
||||
public abstract Alias getToIDAlias();
|
||||
|
||||
public abstract int getChannel();
|
||||
public abstract String getChannel();
|
||||
|
||||
public abstract long getFrequency();
|
||||
|
||||
@@ -216,6 +216,7 @@ public abstract class CallEvent
|
||||
CALL_UNIQUE_ID( "UID Call" ),
|
||||
CALL_NO_TUNER( "Call - No Tuner" ),
|
||||
CALL_TIMEOUT( "Call Timeout" ),
|
||||
DEREGISTER( "Deregister" ),
|
||||
EMERGENCY( "EMERGENCY" ),
|
||||
GPS( "GPS" ),
|
||||
ID_ANI( "ANI" ),
|
||||
|
||||
@@ -296,16 +296,7 @@ public class CallEventModel extends AbstractTableModel
|
||||
case TO_ALIAS:
|
||||
return mEvents.get( rowIndex ).getToIDAlias();
|
||||
case CHANNEL:
|
||||
int channel = mEvents.get( rowIndex ).getChannel();
|
||||
|
||||
if( channel != 0 )
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return mEvents.get( rowIndex ).getChannel();
|
||||
case FREQUENCY:
|
||||
long frequency = mEvents.get( rowIndex ).getFrequency();
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ public class ChannelNode extends ConfigurableNode implements ChannelEventListene
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getForegroundColor()
|
||||
public Color getBackgroundColor()
|
||||
{
|
||||
if( getChannel().getEnabled() )
|
||||
{
|
||||
|
||||
@@ -64,7 +64,7 @@ public class SiteNode extends ConfigurableNode
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getForegroundColor()
|
||||
public Color getBackgroundColor()
|
||||
{
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Enumeration<DefaultMutableTreeNode> nodes = children();
|
||||
@@ -73,9 +73,9 @@ public class SiteNode extends ConfigurableNode
|
||||
{
|
||||
ChannelNode child = (ChannelNode)nodes.nextElement();
|
||||
|
||||
if( child.getForegroundColor() != null )
|
||||
if( child.getBackgroundColor() != null )
|
||||
{
|
||||
return Color.BLUE;
|
||||
return Color.CYAN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ public class SystemNode extends ConfigurableNode
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getForegroundColor()
|
||||
public Color getBackgroundColor()
|
||||
{
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Enumeration<DefaultMutableTreeNode> nodes = children();
|
||||
@@ -73,9 +73,9 @@ public class SystemNode extends ConfigurableNode
|
||||
{
|
||||
SiteNode child = (SiteNode)nodes.nextElement();
|
||||
|
||||
if( child.getForegroundColor() != null )
|
||||
if( child.getBackgroundColor() != null )
|
||||
{
|
||||
return Color.BLUE;
|
||||
return Color.CYAN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package crc;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
public class BCH
|
||||
{
|
||||
public BCH( int n, int k, int t, boolean[] polynomial, boolean sys )
|
||||
{
|
||||
int[] exponents = new int[ n - k + 1 ];
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
179
src/crc/CRCP25NetworkID.java
Normal file
179
src/crc/CRCP25NetworkID.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*******************************************************************************
|
||||
* 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/>
|
||||
******************************************************************************/
|
||||
package crc;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import bits.BitSetBuffer;
|
||||
|
||||
/**
|
||||
* P25 Data Unit ID CRC check utility. Corrects any single bit errors in
|
||||
* either the message or the crc checksum.
|
||||
*/
|
||||
public class CRCP25NetworkID
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( CRCP25NetworkID.class );
|
||||
|
||||
private static final int MESSAGE_START = 0;
|
||||
private static final int CRC_START = 16;
|
||||
private static final int CRC_END = 64;
|
||||
|
||||
private static long[] CHECKSUMS = new long[]
|
||||
{
|
||||
0xCD930BDD3B2Al, //NAC Bit 11 (MSB)
|
||||
0xAB5A8E33A6BEl, //NAC Bit 10
|
||||
0x983E4CC4E874l, //NAC Bit 9
|
||||
0x4C1F2662743Al, //NAC Bit 8
|
||||
0xEB9C98EC0136l, //NAC Bit 7
|
||||
0xB85D47AB3BB0l, //NAC Bit 6
|
||||
0x5C2EA3D59DD8l, //NAC Bit 5
|
||||
0x2E1751EACEECl, //NAC Bit 4
|
||||
0x170BA8F56776l, //NAC Bit 3
|
||||
0xC616DFA78890l, //NAC Bit 2
|
||||
0x630B6FD3C448l, //NAC Bit 1
|
||||
0x3185B7E9E224l, //NAC Bit 0 (LSB)
|
||||
0x18C2DBF4F112l, //DUID Bit 3 (MSB)
|
||||
0xC1F2662743A2l, //DUID Bit 2
|
||||
0xAD6A38CE9AFBl, //DUID Bit 1
|
||||
0x9B2617BA7657l, //DUID Bit 0 (LSB)
|
||||
|
||||
//Single bit errors in the CRC Checksum
|
||||
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,
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static CRC checkAndCorrect( BitSetBuffer message )
|
||||
{
|
||||
long calculated = 0; //Starting value
|
||||
|
||||
/* Iterate the set bits and XOR running checksum with lookup value */
|
||||
for (int i = message.nextSetBit( MESSAGE_START );
|
||||
i >= MESSAGE_START && i < CRC_START;
|
||||
i = message.nextSetBit( i+1 ) )
|
||||
{
|
||||
calculated ^= CHECKSUMS[ i - MESSAGE_START ];
|
||||
}
|
||||
|
||||
long checksum = getChecksum( message );
|
||||
|
||||
if( calculated == checksum )
|
||||
{
|
||||
return CRC.PASSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
int errorLocation = findBitError( calculated ^ checksum );
|
||||
|
||||
if( errorLocation >= 0 )
|
||||
{
|
||||
message.flip( errorLocation );
|
||||
|
||||
return CRC.CORRECTED;
|
||||
}
|
||||
}
|
||||
|
||||
return CRC.FAILED_CRC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the long value of the 48 bit crc checksum and parity bit
|
||||
*/
|
||||
public static long getChecksum( BitSet msg )
|
||||
{
|
||||
long checksum = 0;
|
||||
|
||||
for( int x = CRC_START; x < CRC_END; x++ )
|
||||
{
|
||||
if( msg.get( x ) )
|
||||
{
|
||||
checksum += Long.rotateLeft( 1, CRC_END - 1 - x );
|
||||
}
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies any single bit error position that matches the checksum error.
|
||||
*/
|
||||
public static int findBitError( long checksumError )
|
||||
{
|
||||
/* One bit errors */
|
||||
for( int x = 0; x < 64; x++ )
|
||||
{
|
||||
if( CHECKSUMS[ x ] == checksumError )
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -57,9 +57,9 @@ public class FleetsyncCallEvent extends CallEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChannel()
|
||||
public String getChannel()
|
||||
{
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -57,9 +57,9 @@ public class LJ1200CallEvent extends CallEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChannel()
|
||||
public String getChannel()
|
||||
{
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,7 +25,7 @@ import decode.ltrstandard.LTRStandardMessage;
|
||||
|
||||
public class LTRCallEvent extends CallEvent
|
||||
{
|
||||
private int mChannel;
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
private int mValidCallMessages = 1;
|
||||
|
||||
@@ -33,7 +33,7 @@ public class LTRCallEvent extends CallEvent
|
||||
AliasList aliasList,
|
||||
String fromID,
|
||||
String toID,
|
||||
int channel,
|
||||
String channel,
|
||||
long frequency,
|
||||
String details )
|
||||
{
|
||||
@@ -141,7 +141,7 @@ public class LTRCallEvent extends CallEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChannel()
|
||||
public String getChannel()
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
@@ -162,7 +162,7 @@ public class LTRCallEvent extends CallEvent
|
||||
private String mFromID;
|
||||
private String mToID;
|
||||
private String mDetails;
|
||||
private int mChannel;
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
|
||||
public Builder( CallEventType callEventType )
|
||||
@@ -182,7 +182,7 @@ public class LTRCallEvent extends CallEvent
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder channel( int channel )
|
||||
public Builder channel( String channel )
|
||||
{
|
||||
mChannel = channel;
|
||||
return this;
|
||||
|
||||
@@ -166,7 +166,7 @@ public class LTRNetChannelState extends ChannelState
|
||||
mCallEventModel.add(
|
||||
new LTRCallEvent.Builder( CallEventType.CALL_DETECT )
|
||||
.aliasList( mAliasList )
|
||||
.channel( ltr.getChannel() )
|
||||
.channel( String.valueOf( ltr.getChannel() ) )
|
||||
.to( ltr.getTalkgroupID() )
|
||||
.build() );
|
||||
}
|
||||
@@ -288,7 +288,7 @@ public class LTRNetChannelState extends ChannelState
|
||||
LTRCallEvent event =
|
||||
new LTRCallEvent.Builder( CallEventType.REGISTER )
|
||||
.aliasList( mAliasList )
|
||||
.channel( ltr.getChannel() )
|
||||
.channel( String.valueOf( ltr.getChannel() ) )
|
||||
.frequency( mProcessingChain.getChannel()
|
||||
.getTunerChannel().getFrequency() )
|
||||
.to( ltr.getTalkgroupID() )
|
||||
@@ -354,7 +354,7 @@ public class LTRNetChannelState extends ChannelState
|
||||
{
|
||||
event = new LTRCallEvent.Builder( CallEventType.REGISTER )
|
||||
.aliasList( mAliasList )
|
||||
.channel( message.getChannel() )
|
||||
.channel( String.valueOf( message.getChannel() ) )
|
||||
.frequency( mProcessingChain.getChannel()
|
||||
.getTunerChannel().getFrequency() )
|
||||
.to( message.getTalkgroupID() )
|
||||
@@ -366,7 +366,7 @@ public class LTRNetChannelState extends ChannelState
|
||||
{
|
||||
event = new LTRCallEvent.Builder( CallEventType.CALL )
|
||||
.aliasList( mAliasList )
|
||||
.channel( message.getChannel() )
|
||||
.channel( String.valueOf( message.getChannel() ) )
|
||||
.frequency( mProcessingChain.getChannel()
|
||||
.getTunerChannel().getFrequency() )
|
||||
.to( message.getTalkgroupID() )
|
||||
|
||||
@@ -120,7 +120,7 @@ public class LTRChannelState extends ChannelState
|
||||
new LTRCallEvent.Builder( CallEventType.CALL )
|
||||
.to( ltr.getTalkgroupID() )
|
||||
.aliasList( getAliasList() )
|
||||
.channel( ltr.getChannel() )
|
||||
.channel( String.valueOf( ltr.getChannel() ) )
|
||||
.frequency( ( ltr.getChannel() == mChannelNumber ) ?
|
||||
mProcessingChain.getChannel()
|
||||
.getTunerChannel().getFrequency() : 0 )
|
||||
|
||||
@@ -57,9 +57,9 @@ public class MDCCallEvent extends CallEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChannel()
|
||||
public String getChannel()
|
||||
{
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,14 +24,14 @@ import decode.DecoderType;
|
||||
|
||||
public class MPT1327CallEvent extends CallEvent
|
||||
{
|
||||
private int mChannel;
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
|
||||
public MPT1327CallEvent( CallEventType callEventType,
|
||||
AliasList aliasList,
|
||||
String fromID,
|
||||
String toID,
|
||||
int channel,
|
||||
String channel,
|
||||
long frequency,
|
||||
String details )
|
||||
{
|
||||
@@ -65,7 +65,7 @@ public class MPT1327CallEvent extends CallEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChannel()
|
||||
public String getChannel()
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class MPT1327CallEvent extends CallEvent
|
||||
private String mFromID;
|
||||
private String mToID;
|
||||
private String mDetails;
|
||||
private int mChannel;
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
|
||||
public Builder( CallEventType callEventType )
|
||||
@@ -106,7 +106,7 @@ public class MPT1327CallEvent extends CallEvent
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder channel( int channel )
|
||||
public Builder channel( String channel )
|
||||
{
|
||||
mChannel = channel;
|
||||
return this;
|
||||
|
||||
@@ -115,7 +115,7 @@ public class MPT1327ChannelState extends ChannelState
|
||||
mCallEventModel.add(
|
||||
new MPT1327CallEvent.Builder( CallEventType.REGISTER )
|
||||
.aliasList( getProcessingChain().getAliasList() )
|
||||
.channel( mChannelNumber )
|
||||
.channel( String.valueOf( mChannelNumber ) )
|
||||
.details( "REGISTERED ON NETWORK" )
|
||||
.frequency( mChannelMap.getFrequency( mChannelNumber ) )
|
||||
.from( mpt.getToID() )
|
||||
@@ -127,7 +127,7 @@ public class MPT1327ChannelState extends ChannelState
|
||||
mCallEventModel.add(
|
||||
new MPT1327CallEvent.Builder( CallEventType.ACKNOWLEDGE )
|
||||
.aliasList( getProcessingChain().getAliasList() )
|
||||
.channel( mChannelNumber )
|
||||
.channel( String.valueOf( mChannelNumber ) )
|
||||
.details( "ACK " + identType.getLabel() )
|
||||
.frequency( mChannelMap.getFrequency( mChannelNumber ) )
|
||||
.from( mpt.getFromID() )
|
||||
@@ -139,7 +139,7 @@ public class MPT1327ChannelState extends ChannelState
|
||||
mCallEventModel.add(
|
||||
new MPT1327CallEvent.Builder( CallEventType.REQUEST )
|
||||
.aliasList( getProcessingChain().getAliasList() )
|
||||
.channel( mChannelNumber )
|
||||
.channel( String.valueOf( mChannelNumber ) )
|
||||
.details( ( (MPT1327Message) message ).getRequestString() )
|
||||
.frequency( mChannelMap.getFrequency( mChannelNumber ) )
|
||||
.from( mpt.getFromID() )
|
||||
@@ -150,7 +150,7 @@ public class MPT1327ChannelState extends ChannelState
|
||||
mCallEventModel.add(
|
||||
new MPT1327CallEvent.Builder( CallEventType.STATUS )
|
||||
.aliasList( getProcessingChain().getAliasList() )
|
||||
.channel( mChannelNumber )
|
||||
.channel( String.valueOf( mChannelNumber ) )
|
||||
.details( mpt.getStatusMessage() )
|
||||
.frequency( mChannelMap.getFrequency( mChannelNumber ) )
|
||||
.from( mpt.getFromID() )
|
||||
@@ -233,7 +233,7 @@ public class MPT1327ChannelState extends ChannelState
|
||||
MPT1327CallEvent callStartEvent =
|
||||
new MPT1327CallEvent.Builder( type )
|
||||
.aliasList( traffic.getProcessingChain().getAliasList() )
|
||||
.channel( channelNumber )
|
||||
.channel( String.valueOf( channelNumber ) )
|
||||
.frequency( mChannelMap.getFrequency( channelNumber ) )
|
||||
.from( mpt.getFromID() )
|
||||
.to( mpt.getToID() )
|
||||
@@ -293,7 +293,7 @@ public class MPT1327ChannelState extends ChannelState
|
||||
mCallEventModel.add(
|
||||
new MPT1327CallEvent.Builder( type )
|
||||
.aliasList( getAliasList() )
|
||||
.channel( mChannelNumber )
|
||||
.channel( String.valueOf( mChannelNumber ) )
|
||||
.frequency( mChannelMap.getFrequency( mChannelNumber ) )
|
||||
.from( mFromTalkgroup )
|
||||
.to( mToTalkgroup )
|
||||
|
||||
@@ -24,16 +24,16 @@ import decode.DecoderType;
|
||||
|
||||
public class P25CallEvent extends CallEvent
|
||||
{
|
||||
private int mChannel;
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
|
||||
public P25CallEvent( CallEventType callEventType,
|
||||
AliasList aliasList,
|
||||
String fromID,
|
||||
String toID,
|
||||
int channel,
|
||||
long frequency,
|
||||
String details )
|
||||
AliasList aliasList,
|
||||
String fromID,
|
||||
String toID,
|
||||
String channel,
|
||||
long frequency,
|
||||
String details )
|
||||
{
|
||||
super( DecoderType.MPT1327, callEventType,
|
||||
aliasList, fromID, toID, details );
|
||||
@@ -42,11 +42,11 @@ public class P25CallEvent extends CallEvent
|
||||
mFrequency = frequency;
|
||||
}
|
||||
|
||||
private Alias getAlias( String mpt1327Talkgroup )
|
||||
private Alias getAlias( String talkgroup )
|
||||
{
|
||||
if( hasAliasList() )
|
||||
{
|
||||
return getAliasList().getMPT1327Alias( mpt1327Talkgroup );
|
||||
return getAliasList().getTalkgroupAlias( talkgroup );
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -65,7 +65,7 @@ public class P25CallEvent extends CallEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChannel()
|
||||
public String getChannel()
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class P25CallEvent extends CallEvent
|
||||
private String mFromID;
|
||||
private String mToID;
|
||||
private String mDetails;
|
||||
private int mChannel;
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
|
||||
public Builder( CallEventType callEventType )
|
||||
@@ -106,7 +106,7 @@ public class P25CallEvent extends CallEvent
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder channel( int channel )
|
||||
public Builder channel( String channel )
|
||||
{
|
||||
mChannel = channel;
|
||||
return this;
|
||||
|
||||
@@ -22,12 +22,21 @@ import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import audio.SquelchListener;
|
||||
import audio.SquelchListener.SquelchState;
|
||||
import controller.activity.CallEvent.CallEventType;
|
||||
import controller.channel.ProcessingChain;
|
||||
import controller.state.AuxChannelState;
|
||||
import controller.state.ChannelState;
|
||||
import decode.p25.message.P25Message;
|
||||
import decode.p25.message.pdu.osp.control.RFSSStatusBroadcastExtended;
|
||||
import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.message.tsbk.osp.control.LocationRegistrationResponse;
|
||||
import decode.p25.message.tsbk.osp.control.RFSSStatusBroadcast;
|
||||
import decode.p25.message.tsbk.osp.control.UnitDeregistrationAcknowledge;
|
||||
import decode.p25.message.tsbk.osp.voice.GroupVoiceChannelGrant;
|
||||
import decode.p25.message.tsbk.osp.voice.GroupVoiceChannelGrantUpdate;
|
||||
import decode.p25.message.tsbk.osp.voice.GroupVoiceChannelGrantUpdateExplicit;
|
||||
import decode.p25.message.tsbk.osp.voice.UnitToUnitAnswerRequest;
|
||||
import decode.p25.reference.Vendor;
|
||||
|
||||
public class P25ChannelState extends ChannelState
|
||||
{
|
||||
@@ -123,11 +132,118 @@ public class P25ChannelState extends ChannelState
|
||||
{
|
||||
mSiteAlias = alias.getName();
|
||||
|
||||
broadcastChange( ChangedAttribute.SITE_ALIAS );
|
||||
}
|
||||
else
|
||||
{
|
||||
mSiteAlias = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
broadcastChange( ChangedAttribute.SITE );
|
||||
|
||||
broadcastChange( ChangedAttribute.SITE_ALIAS );
|
||||
}
|
||||
}
|
||||
else if( message instanceof TSBKMessage )
|
||||
{
|
||||
TSBKMessage tsbk = (TSBKMessage)message;
|
||||
|
||||
setState( State.CONTROL );
|
||||
|
||||
if( tsbk.getVendor() == Vendor.STANDARD )
|
||||
{
|
||||
switch( tsbk.getOpcode() )
|
||||
{
|
||||
case GROUP_VOICE_CHANNEL_GRANT:
|
||||
GroupVoiceChannelGrant gvcg = (GroupVoiceChannelGrant)tsbk;
|
||||
|
||||
mCallEventModel.add(
|
||||
new P25CallEvent.Builder( CallEventType.CALL )
|
||||
.aliasList( mAliasList )
|
||||
.channel( gvcg.getChannelIdentifier() + "-" + gvcg.getChannel() )
|
||||
.details( ( gvcg.isEncrypted() ? "ENCRYPTED" : "" ) +
|
||||
( gvcg.isEmergency() ? " EMERGENCY" : "") )
|
||||
.frequency( gvcg.getDownlinkFrequency() )
|
||||
.from( gvcg.getSourceAddress() )
|
||||
.to( gvcg.getGroupAddress() )
|
||||
.build() );
|
||||
break;
|
||||
case GROUP_VOICE_CHANNEL_GRANT_UPDATE:
|
||||
GroupVoiceChannelGrantUpdate gvcgu =
|
||||
(GroupVoiceChannelGrantUpdate)tsbk;
|
||||
mCallEventModel.add(
|
||||
new P25CallEvent.Builder( CallEventType.CALL )
|
||||
.aliasList( mAliasList )
|
||||
.channel( gvcgu.getChannelID1() + "-" + gvcgu.getChannelNumber1() )
|
||||
.details( ( gvcgu.isEncrypted() ? "ENCRYPTED" : "" ) +
|
||||
( gvcgu.isEmergency() ? " EMERGENCY" : "") )
|
||||
.frequency( gvcgu.getDownlinkFrequency() )
|
||||
.to( gvcgu.getGroupAddress1() )
|
||||
.build() );
|
||||
if( gvcgu.getChannelNumber2() != 0 )
|
||||
{
|
||||
mCallEventModel.add(
|
||||
new P25CallEvent.Builder( CallEventType.CALL )
|
||||
.aliasList( mAliasList )
|
||||
.channel( gvcgu.getChannelID2() + "-" + gvcgu.getChannelNumber2() )
|
||||
.details( ( gvcgu.isEncrypted() ? "ENCRYPTED" : "" ) +
|
||||
( gvcgu.isEmergency() ? " EMERGENCY" : "") )
|
||||
.frequency( gvcgu.getDownlinkFrequency() )
|
||||
.to( gvcgu.getGroupAddress2() )
|
||||
.build() );
|
||||
}
|
||||
break;
|
||||
case GROUP_VOICE_CHANNEL_GRANT_UPDATE_EXPLICIT:
|
||||
GroupVoiceChannelGrantUpdateExplicit gvcgue =
|
||||
(GroupVoiceChannelGrantUpdateExplicit)tsbk;
|
||||
|
||||
mCallEventModel.add(
|
||||
new P25CallEvent.Builder( CallEventType.CALL )
|
||||
.aliasList( mAliasList )
|
||||
.channel( gvcgue.getTransmitChannelID() + "-" +
|
||||
gvcgue.getTransmitChannelNumber() )
|
||||
.details( ( gvcgue.isEncrypted() ? "ENCRYPTED" : "" ) +
|
||||
( gvcgue.isEmergency() ? " EMERGENCY" : "") )
|
||||
.frequency( gvcgue.getDownlinkFrequency() )
|
||||
.to( gvcgue.getGroupAddress() )
|
||||
.build() );
|
||||
break;
|
||||
case UNIT_TO_UNIT_ANSWER_REQUEST:
|
||||
UnitToUnitAnswerRequest utuar =
|
||||
(UnitToUnitAnswerRequest)tsbk;
|
||||
mCallEventModel.add(
|
||||
new P25CallEvent.Builder( CallEventType.PAGE )
|
||||
.aliasList( mAliasList )
|
||||
.details( ( utuar.isEmergency() ? "EMERGENCY" : "" ) )
|
||||
.from( utuar.getSourceAddress() )
|
||||
.to( utuar.getTargetAddress() )
|
||||
.build() );
|
||||
break;
|
||||
case LOCATION_REGISTRATION_RESPONSE:
|
||||
LocationRegistrationResponse lrr =
|
||||
(LocationRegistrationResponse)tsbk;
|
||||
|
||||
mCallEventModel.add(
|
||||
new P25CallEvent.Builder( CallEventType.REGISTER )
|
||||
.aliasList( mAliasList )
|
||||
.details( "REG:" + lrr.getResponse().name() +
|
||||
" SITE: " + lrr.getRFSSID() + "-" +
|
||||
lrr.getSiteID() )
|
||||
.from( lrr.getTargetAddress() )
|
||||
.to( lrr.getGroupAddress() )
|
||||
.build() );
|
||||
break;
|
||||
case UNIT_DEREGISTRATION_ACKNOWLEDGE:
|
||||
UnitDeregistrationAcknowledge udr =
|
||||
(UnitDeregistrationAcknowledge)tsbk;
|
||||
|
||||
mCallEventModel.add(
|
||||
new P25CallEvent.Builder( CallEventType.DEREGISTER )
|
||||
.aliasList( mAliasList )
|
||||
.from( udr.getSourceID() )
|
||||
.build() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class P25Panel extends ChannelStatePanel
|
||||
|
||||
private JLabel mSystem = new JLabel( "SYS:" );
|
||||
private JLabel mSite = new JLabel( "Site:" );
|
||||
private JLabel mSiteAlias = new JLabel( "WACN:" );
|
||||
private JLabel mSiteAlias = new JLabel( "" );
|
||||
|
||||
|
||||
public P25Panel( Channel channel )
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
package decode.p25;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import bits.BitSetBuffer;
|
||||
import dsp.fsk.Dibit;
|
||||
import dsp.fsk.P25MessageFramer;
|
||||
|
||||
public class TrellisHalfRate
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( TrellisHalfRate.class );
|
||||
public final static int MAX_ERROR_THRESHOLD = 7;
|
||||
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( TrellisHalfRate.class );
|
||||
|
||||
private ArrayList<ConstellationNode> mConstellationNodes =
|
||||
new ArrayList<ConstellationNode>();
|
||||
@@ -94,7 +97,7 @@ public class TrellisHalfRate
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void decode( BitSetBuffer message, int start, int end )
|
||||
public boolean decode( BitSetBuffer message, int start, int end )
|
||||
{
|
||||
/* load each of the nodes with de-interleaved constellations */
|
||||
for( int index = 0; index < 49; index++ )
|
||||
@@ -104,20 +107,24 @@ public class TrellisHalfRate
|
||||
mConstellationNodes.get( index ).setConstellation( c );
|
||||
}
|
||||
|
||||
// mLog.debug( constellationsToString( " LOADED: ") );
|
||||
//
|
||||
/* test to see if constellations are correct - otherwise correct them */
|
||||
ConstellationNode firstNode = mConstellationNodes.get( 0 );
|
||||
|
||||
if( !firstNode.hasStateDibit( Dibit.D00_PLUS_1 ) || !firstNode.isCorrect() )
|
||||
{
|
||||
firstNode.correctTo( Dibit.D00_PLUS_1 );
|
||||
}
|
||||
int errorCount = firstNode.getErrorCount();
|
||||
|
||||
// mLog.debug( constellationsToString( "CORRECTD: " ) );
|
||||
//
|
||||
// mLog.debug( inputsToString() );
|
||||
//
|
||||
if( errorCount > 0 )
|
||||
{
|
||||
if( errorCount < MAX_ERROR_THRESHOLD )
|
||||
{
|
||||
/* repair the errors */
|
||||
firstNode.correctTo( Dibit.D00_PLUS_1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear constellations from original message */
|
||||
message.clear( start, end );
|
||||
|
||||
@@ -137,6 +144,8 @@ public class TrellisHalfRate
|
||||
message.set( start + ( index * 2 ) + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Constellation getConstellation( BitSetBuffer message, int index )
|
||||
@@ -301,24 +310,18 @@ public class TrellisHalfRate
|
||||
* @return - true - all node connections to the right are correct
|
||||
* false - one or more nodes to the right are incorrect
|
||||
*/
|
||||
public boolean isCorrect()
|
||||
public int getErrorCount()
|
||||
{
|
||||
if( mCorrect )
|
||||
{
|
||||
return mCorrect;
|
||||
}
|
||||
|
||||
if( mConnectedNode == null )
|
||||
{
|
||||
mCorrect = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCorrect = mConnectedNode.isCorrect() &&
|
||||
mConstellation.getInput() == mConnectedNode.getStateDibit();
|
||||
}
|
||||
|
||||
mCorrect = mConstellation.getInput() == mConnectedNode.getStateDibit();
|
||||
|
||||
return mCorrect;
|
||||
return mConnectedNode.getErrorCount() + ( mCorrect ? 0 : 1 );
|
||||
}
|
||||
|
||||
public Dibit getStateDibit()
|
||||
@@ -495,15 +498,17 @@ public class TrellisHalfRate
|
||||
*/
|
||||
public static void main( String[] args )
|
||||
{
|
||||
String original = "00100110000001111000101111110011111000011110100111100001000100100010110000001101100100100010001000100010001000101100111000100010111110001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000101100001110000101000110011100001110";
|
||||
|
||||
BitSetBuffer buffer = new BitSetBuffer( original.length() );
|
||||
Random random = new Random();
|
||||
|
||||
BitSetBuffer buffer = new BitSetBuffer( 196 );
|
||||
|
||||
try
|
||||
{
|
||||
for( int x = 0; x < original.length(); x++ )
|
||||
for( int x = 0; x < 196; x++ )
|
||||
{
|
||||
if( original.substring( x, x + 1 ).contentEquals( "0" ) )
|
||||
int number = random.nextInt( 2 );
|
||||
|
||||
if( number == 1 )
|
||||
{
|
||||
buffer.add( false );
|
||||
}
|
||||
@@ -518,12 +523,11 @@ public class TrellisHalfRate
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
mLog.debug( "ORIGINAL: " + original );
|
||||
mLog.debug( " BUFFER: " + buffer.toString() );
|
||||
|
||||
TrellisHalfRate t = new TrellisHalfRate();
|
||||
|
||||
t.decode( buffer, 64, original.length() );
|
||||
t.decode( buffer, 0, 196 );
|
||||
mLog.debug( " DECODED: " + buffer.toString() );
|
||||
mLog.debug( "Finished!" );
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ public class P25MessageFilterSet extends FilterSet<Message>
|
||||
|
||||
addFilter( new PDUMessageFilter() );
|
||||
addFilter( new TDUMessageFilter() );
|
||||
addFilter( new TSBKMessageFilter() );
|
||||
addFilter( new TSBKMessageFilterSet() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
package decode.p25.message.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.reference.Opcode;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class TSBKMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<Opcode,FilterElement<Opcode>> mFilterElements =
|
||||
new HashMap<Opcode,FilterElement<Opcode>>();
|
||||
|
||||
public TSBKMessageFilter()
|
||||
{
|
||||
super( "TSBK Trunking Signalling Block" );
|
||||
|
||||
for( Opcode opcode: Opcode.values() )
|
||||
{
|
||||
mFilterElements.put( opcode, new FilterElement<Opcode>( opcode ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
TSBKMessage tsbk = (TSBKMessage)message;
|
||||
|
||||
Opcode opcode = tsbk.getOpcode();
|
||||
|
||||
return mFilterElements.get( opcode ).isEnabled();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof TSBKMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mFilterElements.values() );
|
||||
}
|
||||
}
|
||||
200
src/decode/p25/message/filter/TSBKMessageFilterSet.java
Normal file
200
src/decode/p25/message/filter/TSBKMessageFilterSet.java
Normal file
@@ -0,0 +1,200 @@
|
||||
package decode.p25.message.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.message.tsbk.motorola.MotorolaOpcode;
|
||||
import decode.p25.message.tsbk.vendor.VendorOpcode;
|
||||
import decode.p25.reference.Opcode;
|
||||
import decode.p25.reference.Vendor;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
import filter.FilterSet;
|
||||
|
||||
public class TSBKMessageFilterSet extends FilterSet<Message>
|
||||
{
|
||||
public TSBKMessageFilterSet()
|
||||
{
|
||||
super( "TSBK Trunking Signalling Block" );
|
||||
|
||||
addFilter( new StandardOpcodeFilter() );
|
||||
addFilter( new MotorolaOpcodeFilter() );
|
||||
addFilter( new VendorOpcodeFilter() );
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean passes( Message message )
|
||||
// {
|
||||
// if( mEnabled && canProcess( message ) )
|
||||
// {
|
||||
// TSBKMessage tsbk = (TSBKMessage)message;
|
||||
//
|
||||
// switch( tsbk.getVendor() )
|
||||
// {
|
||||
// case STANDARD:
|
||||
// return
|
||||
// }
|
||||
// Opcode opcode = tsbk.getOpcode();
|
||||
//
|
||||
// return mFilterElements.get( opcode ).isEnabled();
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof TSBKMessage;
|
||||
}
|
||||
|
||||
public class StandardOpcodeFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<Opcode,FilterElement<Opcode>> mStandardElements =
|
||||
new HashMap<Opcode,FilterElement<Opcode>>();
|
||||
|
||||
public StandardOpcodeFilter()
|
||||
{
|
||||
super( "Standard Opcode Filter" );
|
||||
|
||||
for( Opcode opcode: Opcode.values() )
|
||||
{
|
||||
if( opcode != Opcode.UNKNOWN )
|
||||
{
|
||||
mStandardElements.put( opcode,
|
||||
new FilterElement<Opcode>( opcode ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
Opcode opcode = ((TSBKMessage)message).getOpcode();
|
||||
|
||||
if( mStandardElements.containsKey( opcode ) )
|
||||
{
|
||||
return mStandardElements.get( opcode ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
|
||||
return ((TSBKMessage)message).getVendor() == Vendor.STANDARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mStandardElements.values() );
|
||||
}
|
||||
}
|
||||
|
||||
public class MotorolaOpcodeFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<MotorolaOpcode,FilterElement<MotorolaOpcode>> mMotorolaElements =
|
||||
new HashMap<MotorolaOpcode,FilterElement<MotorolaOpcode>>();
|
||||
|
||||
public MotorolaOpcodeFilter()
|
||||
{
|
||||
super( "Motorola Opcode Filter" );
|
||||
|
||||
for( MotorolaOpcode opcode: MotorolaOpcode.values() )
|
||||
{
|
||||
if( opcode != MotorolaOpcode.UNKNOWN )
|
||||
{
|
||||
mMotorolaElements.put( opcode,
|
||||
new FilterElement<MotorolaOpcode>( opcode ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
MotorolaOpcode opcode = ((TSBKMessage)message).getMotorolaOpcode();
|
||||
|
||||
if( mMotorolaElements.containsKey( opcode ) )
|
||||
{
|
||||
return mMotorolaElements.get( opcode ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return ((TSBKMessage)message).getVendor() == Vendor.MOTOROLA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mMotorolaElements.values() );
|
||||
}
|
||||
}
|
||||
|
||||
public class VendorOpcodeFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<VendorOpcode,FilterElement<VendorOpcode>> mVendorElements =
|
||||
new HashMap<VendorOpcode,FilterElement<VendorOpcode>>();
|
||||
|
||||
public VendorOpcodeFilter()
|
||||
{
|
||||
super( "Vendor Opcode Filter" );
|
||||
|
||||
for( VendorOpcode opcode: VendorOpcode.values() )
|
||||
{
|
||||
if( opcode != VendorOpcode.UNKNOWN )
|
||||
{
|
||||
mVendorElements.put( opcode,
|
||||
new FilterElement<VendorOpcode>( opcode ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
MotorolaOpcode opcode = ((TSBKMessage)message).getMotorolaOpcode();
|
||||
|
||||
if( mVendorElements.containsKey( opcode ) )
|
||||
{
|
||||
return mVendorElements.get( opcode ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
Vendor vendor = ((TSBKMessage)message).getVendor();
|
||||
|
||||
return vendor != Vendor.STANDARD && vendor != Vendor.MOTOROLA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mVendorElements.values() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,20 @@ package decode.p25.message.tsbk;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public abstract class ChannelGrant extends ServiceMessage
|
||||
public abstract class ChannelGrant extends ServiceMessage
|
||||
implements IdentifierUpdateReceiver
|
||||
{
|
||||
public static final int[] PRIORITY = { 85,86,87 };
|
||||
public static final int[] CHANNEL_ID = { 88,89,90,91 };
|
||||
public static final int[] CHANNEL_NUMBER = { 92,93,94,95,96,97,98,99,100,
|
||||
101,102,103 };
|
||||
|
||||
private IdentifierUpdate mIdentifierUpdate;
|
||||
|
||||
public ChannelGrant( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
@@ -26,13 +31,40 @@ public abstract class ChannelGrant extends ServiceMessage
|
||||
return mMessage.getInt( PRIORITY );
|
||||
}
|
||||
|
||||
public int getChannelID()
|
||||
public int getChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_ID );
|
||||
}
|
||||
|
||||
public int getChannelNumber()
|
||||
public int getChannel()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_NUMBER );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
|
||||
{
|
||||
mIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 1 ];
|
||||
identifiers[ 0 ] = getChannelIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdate, getChannel() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdate, getChannel() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,15 +41,19 @@ public abstract class GroupChannelGrant extends ChannelGrant
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
sb.append( " CHAN:" );
|
||||
sb.append( getChannelID() + "/" + getChannelNumber() );
|
||||
|
||||
sb.append( " FROM:" );
|
||||
sb.append( " SOURCE UNIT:" );
|
||||
sb.append( getSourceAddress() );
|
||||
|
||||
sb.append( " GRP:" );
|
||||
sb.append( " GROUP:" );
|
||||
sb.append( getGroupAddress() );
|
||||
|
||||
sb.append( " CHAN:" );
|
||||
sb.append( getChannelIdentifier() + "-" + getChannel() );
|
||||
|
||||
sb.append( " DN:" + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " UP:" + getUplinkFrequency() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package decode.p25.message.tsbk;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public abstract class GroupChannelGrantExplicit extends ChannelGrant
|
||||
@@ -15,6 +16,9 @@ public abstract class GroupChannelGrantExplicit extends ChannelGrant
|
||||
public static final int[] GROUP_ADDRESS = { 128,129,130,131,132,133,134,135,
|
||||
136,137,138,139,140,141,142,143 };
|
||||
|
||||
private IdentifierUpdate mTransmitIdentifierUpdate;
|
||||
private IdentifierUpdate mReceiveIdentifierUpdate;
|
||||
|
||||
public GroupChannelGrantExplicit( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
@@ -69,4 +73,38 @@ public abstract class GroupChannelGrantExplicit extends ChannelGrant
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS, 4 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
|
||||
{
|
||||
if( identifier == getTransmitChannelID() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveChannelID() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
identifiers[ 0 ] = getTransmitChannelID();
|
||||
identifiers[ 1 ] = getReceiveChannelID();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate, getChannel() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate, getChannel() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ package decode.p25.message.tsbk;
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.P25Message;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
|
||||
import decode.p25.message.tsbk.motorola.MotorolaOpcode;
|
||||
import decode.p25.message.tsbk.vendor.VendorOpcode;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
import decode.p25.reference.Vendor;
|
||||
@@ -56,6 +57,16 @@ public class TSBKMessage extends P25Message
|
||||
return Opcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
|
||||
public MotorolaOpcode getMotorolaOpcode()
|
||||
{
|
||||
return MotorolaOpcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
|
||||
public VendorOpcode getVendorOpcode()
|
||||
{
|
||||
return VendorOpcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
|
||||
@@ -196,9 +196,9 @@ public class TSBKMessageFactory
|
||||
|
||||
switch( motorolaOpcode )
|
||||
{
|
||||
case CHANNEL_CWID_UPDATE:
|
||||
case OP0B:
|
||||
return new ChannelCWIDUpdate( message, duid, aliasList );
|
||||
case SYSTEM_LOADING:
|
||||
case OP09:
|
||||
return new SystemLoading( message, duid, aliasList );
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class ChannelCWIDUpdate extends MotorolaTSBKMessage
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return MotorolaOpcode.CHANNEL_CWID_UPDATE.getDescription();
|
||||
return MotorolaOpcode.OP0B.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
@@ -58,94 +58,31 @@ public class ChannelCWIDUpdate extends MotorolaTSBKMessage
|
||||
public String getCWID()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int char1 = mMessage.getInt( CHARACTER_1 );
|
||||
|
||||
if( char1 != 0 )
|
||||
{
|
||||
sb.append( (char)( char1 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int char2 = mMessage.getInt( CHARACTER_2 );
|
||||
|
||||
if( char2 != 0 )
|
||||
{
|
||||
sb.append( (char)( char2 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char3 = mMessage.getInt( CHARACTER_3 );
|
||||
|
||||
if( char3 != 0 )
|
||||
{
|
||||
sb.append( (char)( char3 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char4 = mMessage.getInt( CHARACTER_4 );
|
||||
|
||||
if( char4 != 0 )
|
||||
{
|
||||
sb.append( (char)( char4 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char5 = mMessage.getInt( CHARACTER_5 );
|
||||
|
||||
if( char5 != 0 )
|
||||
{
|
||||
sb.append( (char)( char5 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char6 = mMessage.getInt( CHARACTER_6 );
|
||||
|
||||
if( char6 != 0 )
|
||||
{
|
||||
sb.append( (char)( char6 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char7 = mMessage.getInt( CHARACTER_7 );
|
||||
|
||||
if( char7 != 0 )
|
||||
{
|
||||
sb.append( (char)( char7 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char8 = mMessage.getInt( CHARACTER_8 );
|
||||
|
||||
if( char8 != 0 )
|
||||
{
|
||||
sb.append( (char)( char8 + 46 ) );
|
||||
}
|
||||
sb.append( getCharacter( CHARACTER_1 ) );
|
||||
sb.append( getCharacter( CHARACTER_2 ) );
|
||||
sb.append( getCharacter( CHARACTER_3 ) );
|
||||
sb.append( getCharacter( CHARACTER_4 ) );
|
||||
sb.append( getCharacter( CHARACTER_5 ) );
|
||||
sb.append( getCharacter( CHARACTER_6 ) );
|
||||
sb.append( getCharacter( CHARACTER_7 ) );
|
||||
sb.append( getCharacter( CHARACTER_8 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getCharacter( int[] field )
|
||||
{
|
||||
int value = mMessage.getInt( field );
|
||||
|
||||
if( value != 0 )
|
||||
{
|
||||
return String.valueOf( (char)( value + 43 ) );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
|
||||
@@ -2,9 +2,70 @@ package decode.p25.message.tsbk.motorola;
|
||||
|
||||
public enum MotorolaOpcode
|
||||
{
|
||||
UNKNOWN_OPCODE_5( "MOTO OPCODE 05 ", "Unknown Opcode 0x05", 0x05 ),
|
||||
SYSTEM_LOADING( "SYSTEM_LOADING ", "System Loading", 0x09 ),
|
||||
CHANNEL_CWID_UPDATE( "CHAN_CWID_UPDATE", "Channel FCC Callsign Update", 0x0B ),
|
||||
OP00( "OP00:UNKNOWN ", "Opcode 0x00 Unknown", 0x00 ),
|
||||
OP01( "OP01:UNKNOWN ", "Opcode 0x01 Unknown", 0x01 ),
|
||||
OP02( "OP02:UNKNOWN ", "Opcode 0x02 Unknown", 0x02 ),
|
||||
OP03( "OP03:UNKNOWN ", "Opcode 0x03 Unknown", 0x03 ),
|
||||
OP04( "OP04:UNKNOWN ", "Opcode 0x04 Unknown", 0x04 ),
|
||||
OP05( "OP05:UNKNOWN ", "Opcode 0x05 Unknown", 0x05 ),
|
||||
OP06( "OP06:UNKNOWN ", "Opcode 0x06 Unknown", 0x06 ),
|
||||
OP07( "OP07:UNKNOWN ", "Opcode 0x07 Unknown", 0x07 ),
|
||||
OP08( "OP08:UNKNOWN ", "Opcode 0x08 Unknown", 0x08 ),
|
||||
OP09( "OP09:SYSTEM_LOAD", "Opcode 0x09 System Loading", 0x09 ),
|
||||
OP0A( "OP0A:UNKNOWN ", "Opcode 0x0A Unknown", 0x0A ),
|
||||
OP0B( "OP0B:CWID_UPDATE", "Opcode 0x0B FCC Callsign", 0x0B ),
|
||||
OP0C( "OP0C:UNKNOWN ", "Opcode 0x0C Unknown", 0x0C ),
|
||||
OP0D( "OP0D:UNKNOWN ", "Opcode 0x0D Unknown", 0x0D ),
|
||||
OP0E( "OP0E:UNKNOWN ", "Opcode 0x0E Unknown", 0x0E ),
|
||||
OP0F( "OP0F:UNKNOWN ", "Opcode 0x0F Unknown", 0x0F ),
|
||||
OP10( "OP10:UNKNOWN ", "Opcode 0x10 Unknown", 0x10 ),
|
||||
OP11( "OP11:UNKNOWN ", "Opcode 0x11 Unknown", 0x11 ),
|
||||
OP12( "OP12:UNKNOWN ", "Opcode 0x12 Unknown", 0x12 ),
|
||||
OP13( "OP13:UNKNOWN ", "Opcode 0x13 Unknown", 0x13 ),
|
||||
OP14( "OP14:UNKNOWN ", "Opcode 0x14 Unknown", 0x14 ),
|
||||
OP15( "OP15:UNKNOWN ", "Opcode 0x15 Unknown", 0x15 ),
|
||||
OP16( "OP16:UNKNOWN ", "Opcode 0x16 Unknown", 0x16 ),
|
||||
OP17( "OP17:UNKNOWN ", "Opcode 0x17 Unknown", 0x17 ),
|
||||
OP18( "OP18:UNKNOWN ", "Opcode 0x18 Unknown", 0x18 ),
|
||||
OP19( "OP19:UNKNOWN ", "Opcode 0x19 Unknown", 0x19 ),
|
||||
OP1A( "OP1A:UNKNOWN ", "Opcode 0x1A Unknown", 0x1A ),
|
||||
OP1B( "OP1B:UNKNOWN ", "Opcode 0x1B Unknown", 0x1B ),
|
||||
OP1C( "OP1C:UNKNOWN ", "Opcode 0x1C Unknown", 0x1C ),
|
||||
OP1D( "OP1D:UNKNOWN ", "Opcode 0x1D Unknown", 0x1D ),
|
||||
OP1E( "OP1E:UNKNOWN ", "Opcode 0x1E Unknown", 0x1E ),
|
||||
OP1F( "OP1F:UNKNOWN ", "Opcode 0x1F Unknown", 0x1F ),
|
||||
OP20( "OP20:UNKNOWN ", "Opcode 0x20 Unknown", 0x20 ),
|
||||
OP21( "OP21:UNKNOWN ", "Opcode 0x21 Unknown", 0x21 ),
|
||||
OP22( "OP22:UNKNOWN ", "Opcode 0x22 Unknown", 0x22 ),
|
||||
OP23( "OP23:UNKNOWN ", "Opcode 0x23 Unknown", 0x23 ),
|
||||
OP24( "OP24:UNKNOWN ", "Opcode 0x24 Unknown", 0x24 ),
|
||||
OP25( "OP25:UNKNOWN ", "Opcode 0x25 Unknown", 0x25 ),
|
||||
OP26( "OP26:UNKNOWN ", "Opcode 0x26 Unknown", 0x26 ),
|
||||
OP27( "OP27:UNKNOWN ", "Opcode 0x27 Unknown", 0x27 ),
|
||||
OP28( "OP28:UNKNOWN ", "Opcode 0x28 Unknown", 0x28 ),
|
||||
OP29( "OP29:UNKNOWN ", "Opcode 0x29 Unknown", 0x29 ),
|
||||
OP2A( "OP2A:UNKNOWN ", "Opcode 0x2A Unknown", 0x2A ),
|
||||
OP2B( "OP2B:UNKNOWN ", "Opcode 0x2B Unknown", 0x2B ),
|
||||
OP2C( "OP2C:UNKNOWN ", "Opcode 0x2C Unknown", 0x2C ),
|
||||
OP2D( "OP2D:UNKNOWN ", "Opcode 0x2D Unknown", 0x2D ),
|
||||
OP2E( "OP2E:UNKNOWN ", "Opcode 0x2E Unknown", 0x2E ),
|
||||
OP2F( "OP2F:UNKNOWN ", "Opcode 0x2F Unknown", 0x2F ),
|
||||
OP30( "OP30:UNKNOWN ", "Opcode 0x30 Unknown", 0x30 ),
|
||||
OP31( "OP31:UNKNOWN ", "Opcode 0x31 Unknown", 0x31 ),
|
||||
OP32( "OP32:UNKNOWN ", "Opcode 0x32 Unknown", 0x32 ),
|
||||
OP33( "OP33:UNKNOWN ", "Opcode 0x33 Unknown", 0x33 ),
|
||||
OP34( "OP34:UNKNOWN ", "Opcode 0x34 Unknown", 0x34 ),
|
||||
OP35( "OP35:UNKNOWN ", "Opcode 0x35 Unknown", 0x35 ),
|
||||
OP36( "OP36:UNKNOWN ", "Opcode 0x36 Unknown", 0x36 ),
|
||||
OP37( "OP37:UNKNOWN ", "Opcode 0x37 Unknown", 0x37 ),
|
||||
OP38( "OP38:UNKNOWN ", "Opcode 0x38 Unknown", 0x38 ),
|
||||
OP39( "OP39:UNKNOWN ", "Opcode 0x39 Unknown", 0x39 ),
|
||||
OP3A( "OP3A:UNKNOWN ", "Opcode 0x3A Unknown", 0x3A ),
|
||||
OP3B( "OP3B:UNKNOWN ", "Opcode 0x3B Unknown", 0x3B ),
|
||||
OP3C( "OP3C:UNKNOWN ", "Opcode 0x3C Unknown", 0x3C ),
|
||||
OP3D( "OP3D:UNKNOWN ", "Opcode 0x3D Unknown", 0x3D ),
|
||||
OP3E( "OP3E:UNKNOWN ", "Opcode 0x3E Unknown", 0x3E ),
|
||||
OP3F( "OP3F:UNKNOWN ", "Opcode 0x3F Unknown", 0x3F ),
|
||||
UNKNOWN( "UNKNOWN ", "Unknown", -1 );
|
||||
|
||||
private String mLabel;
|
||||
@@ -23,6 +84,11 @@ public enum MotorolaOpcode
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getLabel();
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return mDescription;
|
||||
@@ -35,14 +101,9 @@ public enum MotorolaOpcode
|
||||
|
||||
public static MotorolaOpcode fromValue( int value )
|
||||
{
|
||||
switch( value )
|
||||
if( 0 <= value && value <= 0x3F )
|
||||
{
|
||||
case 0x05:
|
||||
return UNKNOWN_OPCODE_5;
|
||||
case 0x09:
|
||||
return SYSTEM_LOADING;
|
||||
case 0x0B:
|
||||
return CHANNEL_CWID_UPDATE;
|
||||
return MotorolaOpcode.values()[ value ];
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
|
||||
@@ -16,7 +16,7 @@ public class SystemLoading extends MotorolaTSBKMessage
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return MotorolaOpcode.SYSTEM_LOADING.getLabel();
|
||||
return MotorolaOpcode.OP09.getLabel();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -52,7 +52,7 @@ public class LocationRegistrationResponse extends TSBKMessage
|
||||
|
||||
public String getGroupAddress()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS, 6 );
|
||||
return mMessage.getHex( GROUP_ADDRESS, 4 );
|
||||
}
|
||||
|
||||
public String getRFSSID()
|
||||
|
||||
@@ -54,7 +54,8 @@ public class TimeAndDateAnnouncement extends TSBKMessage
|
||||
{
|
||||
sb.append( " DATE-TIME:" );
|
||||
}
|
||||
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( mTimeFormatter.format( new Date( getDateTimestamp() ) ) );
|
||||
|
||||
return sb.toString();
|
||||
|
||||
@@ -20,4 +20,5 @@ public class GroupVoiceChannelGrant extends GroupChannelGrant
|
||||
{
|
||||
return Opcode.GROUP_VOICE_CHANNEL_GRANT.getDescription();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public class TelephoneInterconnectVoiceChannelGrant extends UnitChannelGrant
|
||||
}
|
||||
|
||||
sb.append( " CHAN:" );
|
||||
sb.append( getChannelID() + "/" + getChannelNumber() );
|
||||
sb.append( getChannelIdentifier() + "/" + getChannel() );
|
||||
|
||||
sb.append( " CALL TIMER:" );
|
||||
sb.append( getCallTimer() );
|
||||
|
||||
@@ -3,6 +3,7 @@ package decode.p25.message.tsbk.osp.voice;
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.UnitChannelGrant;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
|
||||
@@ -20,4 +21,28 @@ public class UnitToUnitVoiceChannelGrant extends UnitChannelGrant
|
||||
{
|
||||
return Opcode.UNIT_TO_UNIT_VOICE_CHANNEL_GRANT.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
sb.append( " SOURCE UNIT:" );
|
||||
sb.append( getSourceAddress() );
|
||||
|
||||
sb.append( " TARGET UNIT:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " CHAN:" + getChannelIdentifier() + "-" + getChannel() );
|
||||
sb.append( " DN:" + getDownlinkFrequency() );
|
||||
sb.append( " UP:" + getUplinkFrequency() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
111
src/decode/p25/message/tsbk/vendor/VendorOpcode.java
vendored
Normal file
111
src/decode/p25/message/tsbk/vendor/VendorOpcode.java
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
package decode.p25.message.tsbk.vendor;
|
||||
|
||||
public enum VendorOpcode
|
||||
{
|
||||
OP00( "OPCODE 00 ", "VENDOR OPCODE 0x00", 0x00 ),
|
||||
OP01( "OPCODE 01 ", "VENDOR OPCODE 0x01", 0x01 ),
|
||||
OP02( "OPCODE 02 ", "VENDOR OPCODE 0x02", 0x02 ),
|
||||
OP03( "OPCODE 03 ", "VENDOR OPCODE 0x03", 0x03 ),
|
||||
OP04( "OPCODE 04 ", "VENDOR OPCODE 0x04", 0x04 ),
|
||||
OP05( "OPCODE 05 ", "VENDOR OPCODE 0x05", 0x05 ),
|
||||
OP06( "OPCODE 06 ", "VENDOR OPCODE 0x06", 0x06 ),
|
||||
OP07( "OPCODE 07 ", "VENDOR OPCODE 0x07", 0x07 ),
|
||||
OP08( "OPCODE 08 ", "VENDOR OPCODE 0x08", 0x08 ),
|
||||
OP09( "OPCODE 09 ", "VENDOR OPCODE 0x09", 0x09 ),
|
||||
OP0A( "OPCODE 0A ", "VENDOR OPCODE 0x0A", 0x0A ),
|
||||
OP0B( "OPCODE 0B ", "VENDOR OPCODE 0x0B", 0x0B ),
|
||||
OP0C( "OPCODE 0C ", "VENDOR OPCODE 0x0C", 0x0C ),
|
||||
OP0D( "OPCODE 0D ", "VENDOR OPCODE 0x0D", 0x0D ),
|
||||
OP0E( "OPCODE 0E ", "VENDOR OPCODE 0x0E", 0x0E ),
|
||||
OP0F( "OPCODE 0F ", "VENDOR OPCODE 0x0F", 0x0F ),
|
||||
OP10( "OPCODE 10 ", "VENDOR OPCODE 0x10", 0x10 ),
|
||||
OP11( "OPCODE 11 ", "VENDOR OPCODE 0x11", 0x11 ),
|
||||
OP12( "OPCODE 12 ", "VENDOR OPCODE 0x12", 0x12 ),
|
||||
OP13( "OPCODE 13 ", "VENDOR OPCODE 0x13", 0x13 ),
|
||||
OP14( "OPCODE 14 ", "VENDOR OPCODE 0x14", 0x14 ),
|
||||
OP15( "OPCODE 15 ", "VENDOR OPCODE 0x15", 0x15 ),
|
||||
OP16( "OPCODE 16 ", "VENDOR OPCODE 0x16", 0x16 ),
|
||||
OP17( "OPCODE 17 ", "VENDOR OPCODE 0x17", 0x17 ),
|
||||
OP18( "OPCODE 18 ", "VENDOR OPCODE 0x18", 0x18 ),
|
||||
OP19( "OPCODE 19 ", "VENDOR OPCODE 0x19", 0x19 ),
|
||||
OP1A( "OPCODE 1A ", "VENDOR OPCODE 0x1A", 0x1A ),
|
||||
OP1B( "OPCODE 1B ", "VENDOR OPCODE 0x1B", 0x1B ),
|
||||
OP1C( "OPCODE 1C ", "VENDOR OPCODE 0x1C", 0x1C ),
|
||||
OP1D( "OPCODE 1D ", "VENDOR OPCODE 0x1D", 0x1D ),
|
||||
OP1E( "OPCODE 1E ", "VENDOR OPCODE 0x1E", 0x1E ),
|
||||
OP1F( "OPCODE 1F ", "VENDOR OPCODE 0x1F", 0x1F ),
|
||||
OP20( "OPCODE 20 ", "VENDOR OPCODE 0x20", 0x20 ),
|
||||
OP21( "OPCODE 21 ", "VENDOR OPCODE 0x21", 0x21 ),
|
||||
OP22( "OPCODE 22 ", "VENDOR OPCODE 0x22", 0x22 ),
|
||||
OP23( "OPCODE 23 ", "VENDOR OPCODE 0x23", 0x23 ),
|
||||
OP24( "OPCODE 24 ", "VENDOR OPCODE 0x24", 0x24 ),
|
||||
OP25( "OPCODE 25 ", "VENDOR OPCODE 0x25", 0x25 ),
|
||||
OP26( "OPCODE 26 ", "VENDOR OPCODE 0x26", 0x26 ),
|
||||
OP27( "OPCODE 27 ", "VENDOR OPCODE 0x27", 0x27 ),
|
||||
OP28( "OPCODE 28 ", "VENDOR OPCODE 0x28", 0x28 ),
|
||||
OP29( "OPCODE 29 ", "VENDOR OPCODE 0x29", 0x29 ),
|
||||
OP2A( "OPCODE 2A ", "VENDOR OPCODE 0x2A", 0x2A ),
|
||||
OP2B( "OPCODE 2B ", "VENDOR OPCODE 0x2B", 0x2B ),
|
||||
OP2C( "OPCODE 2C ", "VENDOR OPCODE 0x2C", 0x2C ),
|
||||
OP2D( "OPCODE 2D ", "VENDOR OPCODE 0x2D", 0x2D ),
|
||||
OP2E( "OPCODE 2E ", "VENDOR OPCODE 0x2E", 0x2E ),
|
||||
OP2F( "OPCODE 2F ", "VENDOR OPCODE 0x2F", 0x2F ),
|
||||
OP30( "OPCODE 30 ", "VENDOR OPCODE 0x30", 0x30 ),
|
||||
OP31( "OPCODE 31 ", "VENDOR OPCODE 0x31", 0x31 ),
|
||||
OP32( "OPCODE 32 ", "VENDOR OPCODE 0x32", 0x32 ),
|
||||
OP33( "OPCODE 33 ", "VENDOR OPCODE 0x33", 0x33 ),
|
||||
OP34( "OPCODE 34 ", "VENDOR OPCODE 0x34", 0x34 ),
|
||||
OP35( "OPCODE 35 ", "VENDOR OPCODE 0x35", 0x35 ),
|
||||
OP36( "OPCODE 36 ", "VENDOR OPCODE 0x36", 0x36 ),
|
||||
OP37( "OPCODE 37 ", "VENDOR OPCODE 0x37", 0x37 ),
|
||||
OP38( "OPCODE 38 ", "VENDOR OPCODE 0x38", 0x38 ),
|
||||
OP39( "OPCODE 39 ", "VENDOR OPCODE 0x39", 0x39 ),
|
||||
OP3A( "OPCODE 3A ", "VENDOR OPCODE 0x3A", 0x3A ),
|
||||
OP3B( "OPCODE 3B ", "VENDOR OPCODE 0x3B", 0x3B ),
|
||||
OP3C( "OPCODE 3C ", "VENDOR OPCODE 0x3C", 0x3C ),
|
||||
OP3D( "OPCODE 3D ", "VENDOR OPCODE 0x3D", 0x3D ),
|
||||
OP3E( "OPCODE 3E ", "VENDOR OPCODE 0x3E", 0x3E ),
|
||||
OP3F( "OPCODE 3F ", "VENDOR OPCODE 0x3F", 0x3F ),
|
||||
UNKNOWN( "UNKNOWN ", "Unknown", -1 );
|
||||
|
||||
private String mLabel;
|
||||
private String mDescription;
|
||||
private int mCode;
|
||||
|
||||
private VendorOpcode( String label, String description, int code )
|
||||
{
|
||||
mLabel = label;
|
||||
mDescription = description;
|
||||
mCode = code;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getLabel();
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
public int getCode()
|
||||
{
|
||||
return mCode;
|
||||
}
|
||||
|
||||
public static VendorOpcode fromValue( int value )
|
||||
{
|
||||
if( 0 <= value && value <= 0x3F )
|
||||
{
|
||||
return VendorOpcode.values()[ value ];
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,13 @@ package decode.p25.reference;
|
||||
|
||||
public enum ServiceAccessPoint
|
||||
{
|
||||
SAP_0( "0", 0 ),
|
||||
SAP_1( "1", 1 ),
|
||||
SAP_2( "2", 2 ),
|
||||
SAP_3( "3", 3 ),
|
||||
SAP_4( "4", 4 ),
|
||||
SAP_5( "5", 5 ),
|
||||
SAP_6( "6", 6 ),
|
||||
UNENCRYPTED_USER_DATA( "0", 0 ),
|
||||
ENCRYPTED_USER_DATA( "1", 1 ),
|
||||
CIRCUIT_DATA( "2", 2 ),
|
||||
CIRCUIT_DATA_CONTROL( "3", 3 ),
|
||||
PACKET_DATA( "4", 4 ),
|
||||
ADDRESS_RESOLUTION_PROTOCOL( "5", 5 ),
|
||||
SNDCP_PACKET_DATA_CONTROL( "6", 6 ),
|
||||
SAP_7( "7", 7 ),
|
||||
SAP_8( "8", 8 ),
|
||||
SAP_9( "9", 9 ),
|
||||
@@ -33,17 +33,17 @@ public enum ServiceAccessPoint
|
||||
SAP_28( "28", 28 ),
|
||||
SAP_29( "29", 29 ),
|
||||
SAP_30( "30", 30 ),
|
||||
SAP_31( "31", 31 ),
|
||||
SAP_32( "32", 32 ),
|
||||
SAP_33( "33", 33 ),
|
||||
SAP_34( "34", 34 ),
|
||||
SAP_35( "35", 35 ),
|
||||
SAP_36( "36", 36 ),
|
||||
SAP_37( "37", 37 ),
|
||||
SAP_38( "38", 38 ),
|
||||
SAP_39( "39", 39 ),
|
||||
SAP_40( "40", 40 ),
|
||||
SAP_41( "41", 41 ),
|
||||
EXTENDED_ADDRESS( "31", 31 ),
|
||||
REGISTRATION_AND_AUTHORIZATION( "32", 32 ),
|
||||
CHANNEL_REASSIGNMENT( "33", 33 ),
|
||||
SYSTEM_CONFIGURATION( "34", 34 ),
|
||||
MR_LOOPBACK( "35", 35 ),
|
||||
MR_STATISTICS( "36", 36 ),
|
||||
MR_OUT_OF_SERVICE( "37", 37 ),
|
||||
MR_PAGING( "38", 38 ),
|
||||
MR_CONFIGURATION( "39", 39 ),
|
||||
UNENCRYPTED_KEY_MANAGEMENT_MESSAGE( "40", 40 ),
|
||||
ENCRYPTED_KEY_MANAGEMENT_MESSAGE( "41", 41 ),
|
||||
SAP_42( "42", 42 ),
|
||||
SAP_43( "43", 43 ),
|
||||
SAP_44( "44", 44 ),
|
||||
|
||||
@@ -24,7 +24,7 @@ import decode.DecoderType;
|
||||
|
||||
public class PassportCallEvent extends CallEvent
|
||||
{
|
||||
private int mChannel;
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
private int mValidCallMessages = 1;
|
||||
|
||||
@@ -32,7 +32,7 @@ public class PassportCallEvent extends CallEvent
|
||||
AliasList aliasList,
|
||||
String fromID,
|
||||
String toID,
|
||||
int channel,
|
||||
String channel,
|
||||
long frequency,
|
||||
String details )
|
||||
{
|
||||
@@ -99,7 +99,7 @@ public class PassportCallEvent extends CallEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChannel()
|
||||
public String getChannel()
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
@@ -120,7 +120,7 @@ public class PassportCallEvent extends CallEvent
|
||||
private String mFromID;
|
||||
private String mToID;
|
||||
private String mDetails;
|
||||
private int mChannel;
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
|
||||
public Builder( CallEventType callEventType )
|
||||
@@ -140,7 +140,7 @@ public class PassportCallEvent extends CallEvent
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder channel( int channel )
|
||||
public Builder channel( String channel )
|
||||
{
|
||||
mChannel = channel;
|
||||
return this;
|
||||
|
||||
@@ -146,7 +146,7 @@ public class PassportChannelState extends ChannelState
|
||||
mCurrentCallEvent = new PassportCallEvent
|
||||
.Builder( CallEventType.CALL )
|
||||
.aliasList( mAliasList )
|
||||
.channel( mChannelNumber )
|
||||
.channel( String.valueOf( mChannelNumber ) )
|
||||
.frequency( passport.getLCNFrequency() )
|
||||
.to( String.valueOf( passport.getTalkgroupID() ) )
|
||||
.build();
|
||||
@@ -179,7 +179,7 @@ public class PassportChannelState extends ChannelState
|
||||
PassportCallEvent event = new PassportCallEvent
|
||||
.Builder( CallEventType.CALL_DETECT )
|
||||
.aliasList( mAliasList )
|
||||
.channel( lcn )
|
||||
.channel( String.valueOf( lcn ) )
|
||||
.details( "Site: " + passport.getSite() )
|
||||
.frequency( passport.getLCNFrequency() )
|
||||
.to( tg )
|
||||
@@ -220,7 +220,7 @@ public class PassportChannelState extends ChannelState
|
||||
mCallEventModel.add( new PassportCallEvent
|
||||
.Builder( CallEventType.REGISTER )
|
||||
.aliasList( mAliasList )
|
||||
.channel( passport.getLCN() )
|
||||
.channel( String.valueOf( passport.getLCN() ) )
|
||||
.frequency( passport.getLCNFrequency() )
|
||||
.to( passport.getToID() )
|
||||
.build() );
|
||||
|
||||
@@ -12,6 +12,8 @@ import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import bits.BitSetFullException;
|
||||
import bits.SyncPatternMatcher;
|
||||
import crc.CRC;
|
||||
import crc.CRCP25NetworkID;
|
||||
import decode.p25.P25Interleave;
|
||||
import decode.p25.TrellisHalfRate;
|
||||
import decode.p25.message.P25Message;
|
||||
@@ -218,13 +220,22 @@ public class P25MessageFramer implements Listener<Dibit>
|
||||
switch( mDUID )
|
||||
{
|
||||
case NID:
|
||||
int value = mMessage.getInt( P25Message.DUID );
|
||||
|
||||
DataUnitID duid = DataUnitID.fromValue( value );
|
||||
|
||||
if( duid != DataUnitID.UNKN )
|
||||
CRC crc = CRCP25NetworkID.checkAndCorrect( mMessage );
|
||||
|
||||
if( crc != CRC.FAILED_CRC )
|
||||
{
|
||||
setDUID( duid );
|
||||
int value = mMessage.getInt( P25Message.DUID );
|
||||
|
||||
DataUnitID duid = DataUnitID.fromValue( value );
|
||||
|
||||
if( duid != DataUnitID.UNKN )
|
||||
{
|
||||
setDUID( duid );
|
||||
}
|
||||
else
|
||||
{
|
||||
mComplete = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -247,155 +258,187 @@ public class P25MessageFramer implements Listener<Dibit>
|
||||
/* Remove interleaving */
|
||||
P25Interleave.deinterleave( mMessage, PDU0_BEGIN, PDU0_END );
|
||||
|
||||
/* Remove trellis encoding */
|
||||
mHalfRate.decode( mMessage, PDU0_BEGIN, PDU0_END );
|
||||
|
||||
setDUID( DataUnitID.PDU1 );
|
||||
|
||||
mMessage.setPointer( PDU1_BEGIN );
|
||||
/* Remove trellis encoding - abort processing if we have an
|
||||
* unsuccessful decode due to excessive errors */
|
||||
if( mHalfRate.decode( mMessage, PDU0_BEGIN, PDU0_END ) )
|
||||
{
|
||||
setDUID( DataUnitID.PDU1 );
|
||||
|
||||
mMessage.setPointer( PDU1_BEGIN );
|
||||
}
|
||||
else
|
||||
{
|
||||
mComplete = true;
|
||||
}
|
||||
break;
|
||||
case PDU1:
|
||||
/* Remove interleaving */
|
||||
P25Interleave.deinterleave( mMessage, PDU1_BEGIN, PDU1_END );
|
||||
|
||||
/* Remove trellis encoding */
|
||||
mHalfRate.decode( mMessage, PDU1_BEGIN, PDU1_END );
|
||||
|
||||
if( mMessage.getInt( PDUMessage.BLOCKS_TO_FOLLOW ) == 1 )
|
||||
/* Remove trellis encoding - abort processing if we have an
|
||||
* unsuccessful decode due to excessive errors */
|
||||
if( mHalfRate.decode( mMessage, PDU1_BEGIN, PDU1_END ) )
|
||||
{
|
||||
mMessage.setSize( PDU2_BEGIN );
|
||||
|
||||
PDUMessage pduMessage1 = PDUMessageFactory.getMessage(
|
||||
mMessage.copy(), DataUnitID.PDU1, mAliasList );
|
||||
if( mMessage.getInt( PDUMessage.BLOCKS_TO_FOLLOW ) == 1 )
|
||||
{
|
||||
mMessage.setSize( PDU2_BEGIN );
|
||||
|
||||
PDUMessage pduMessage1 = PDUMessageFactory.getMessage(
|
||||
mMessage.copy(), DataUnitID.PDU1, mAliasList );
|
||||
|
||||
dispatch( pduMessage1 );
|
||||
|
||||
mComplete = true;
|
||||
dispatch( pduMessage1 );
|
||||
|
||||
mComplete = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
setDUID( DataUnitID.PDU2 );
|
||||
|
||||
mMessage.setPointer( PDU2_BEGIN );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setDUID( DataUnitID.PDU2 );
|
||||
|
||||
mMessage.setPointer( PDU2_BEGIN );
|
||||
mComplete = true;
|
||||
}
|
||||
break;
|
||||
case PDU2:
|
||||
/* Remove interleaving */
|
||||
P25Interleave.deinterleave( mMessage, PDU2_BEGIN, PDU2_END );
|
||||
|
||||
/* Remove trellis encoding */
|
||||
mHalfRate.decode( mMessage, PDU2_BEGIN, PDU2_END );
|
||||
|
||||
if( mMessage.getInt( PDUMessage.BLOCKS_TO_FOLLOW ) == 2 )
|
||||
/* Remove trellis encoding - abort processing if we have an
|
||||
* unsuccessful decode due to excessive errors */
|
||||
if( mHalfRate.decode( mMessage, PDU2_BEGIN, PDU2_END ) )
|
||||
{
|
||||
mMessage.setSize( PDU3_BEGIN );
|
||||
|
||||
PDUMessage pduMessage2 = PDUMessageFactory.getMessage(
|
||||
mMessage.copy(), DataUnitID.PDU2, mAliasList );
|
||||
if( mMessage.getInt( PDUMessage.BLOCKS_TO_FOLLOW ) == 2 )
|
||||
{
|
||||
mMessage.setSize( PDU3_BEGIN );
|
||||
|
||||
PDUMessage pduMessage2 = PDUMessageFactory.getMessage(
|
||||
mMessage.copy(), DataUnitID.PDU2, mAliasList );
|
||||
|
||||
dispatch( pduMessage2 );
|
||||
|
||||
mComplete = true;
|
||||
dispatch( pduMessage2 );
|
||||
|
||||
mComplete = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
setDUID( DataUnitID.PDU3 );
|
||||
|
||||
mMessage.setPointer( PDU3_BEGIN );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setDUID( DataUnitID.PDU3 );
|
||||
|
||||
mMessage.setPointer( PDU3_BEGIN );
|
||||
mComplete = true;
|
||||
}
|
||||
break;
|
||||
case PDU3:
|
||||
/* Remove interleaving */
|
||||
P25Interleave.deinterleave( mMessage, PDU3_BEGIN, PDU3_END );
|
||||
|
||||
/* Remove trellis encoding */
|
||||
mHalfRate.decode( mMessage, PDU3_BEGIN, PDU3_END );
|
||||
|
||||
mMessage.setSize( PDU3_DECODED_END );
|
||||
|
||||
PDUMessage pduMessage3 = PDUMessageFactory.getMessage(
|
||||
mMessage.copy(), DataUnitID.PDU3, mAliasList );
|
||||
/* Remove trellis encoding - abort processing if we have an
|
||||
* unsuccessful decode due to excessive errors */
|
||||
if( mHalfRate.decode( mMessage, PDU3_BEGIN, PDU3_END ) )
|
||||
{
|
||||
mMessage.setSize( PDU3_DECODED_END );
|
||||
|
||||
PDUMessage pduMessage3 = PDUMessageFactory.getMessage(
|
||||
mMessage.copy(), DataUnitID.PDU3, mAliasList );
|
||||
|
||||
dispatch( pduMessage3 );
|
||||
dispatch( pduMessage3 );
|
||||
}
|
||||
|
||||
mComplete = true;
|
||||
break;
|
||||
case TDU:
|
||||
mComplete = true;
|
||||
dispatch( new TDUMessage( mMessage.copy(), mDUID, mAliasList ) );
|
||||
mComplete = true;
|
||||
break;
|
||||
case TDULC:
|
||||
mComplete = true;
|
||||
dispatch( new P25Message( mMessage.copy(), mDUID, mAliasList ) );
|
||||
mComplete = true;
|
||||
break;
|
||||
case TSBK1:
|
||||
/* Remove interleaving */
|
||||
P25Interleave.deinterleave( mMessage, TSBK_BEGIN, TSBK_END );
|
||||
|
||||
/* Remove trellis encoding */
|
||||
mHalfRate.decode( mMessage, TSBK_BEGIN, TSBK_END );
|
||||
|
||||
BitSetBuffer tsbkBuffer1 = mMessage.copy();
|
||||
tsbkBuffer1.setSize( TSBK_DECODED_END );
|
||||
|
||||
TSBKMessage tsbkMessage1 = TSBKMessageFactory.getMessage(
|
||||
tsbkBuffer1, DataUnitID.TSBK1, mAliasList );
|
||||
|
||||
if( tsbkMessage1.isLastBlock() )
|
||||
/* Remove trellis encoding - abort processing if we have an
|
||||
* unsuccessful decode due to excessive errors */
|
||||
if( mHalfRate.decode( mMessage, TSBK_BEGIN, TSBK_END ) )
|
||||
{
|
||||
mComplete = true;
|
||||
BitSetBuffer tsbkBuffer1 = mMessage.copy();
|
||||
tsbkBuffer1.setSize( TSBK_DECODED_END );
|
||||
|
||||
TSBKMessage tsbkMessage1 = TSBKMessageFactory.getMessage(
|
||||
tsbkBuffer1, DataUnitID.TSBK1, mAliasList );
|
||||
|
||||
if( tsbkMessage1.isLastBlock() )
|
||||
{
|
||||
mComplete = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
setDUID( DataUnitID.TSBK2 );
|
||||
mMessage.setPointer( TSBK_BEGIN );
|
||||
}
|
||||
|
||||
dispatch( tsbkMessage1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
setDUID( DataUnitID.TSBK2 );
|
||||
mMessage.setPointer( TSBK_BEGIN );
|
||||
mComplete = true;
|
||||
}
|
||||
|
||||
dispatch( tsbkMessage1 );
|
||||
break;
|
||||
case TSBK2:
|
||||
/* Remove interleaving */
|
||||
P25Interleave.deinterleave( mMessage, TSBK_BEGIN, TSBK_END );
|
||||
|
||||
/* Remove trellis encoding */
|
||||
mHalfRate.decode( mMessage, TSBK_BEGIN, TSBK_END );
|
||||
|
||||
BitSetBuffer tsbkBuffer2 = mMessage.copy();
|
||||
tsbkBuffer2.setSize( TSBK_DECODED_END );
|
||||
|
||||
TSBKMessage tsbkMessage2 = TSBKMessageFactory.getMessage(
|
||||
tsbkBuffer2, DataUnitID.TSBK2, mAliasList );
|
||||
|
||||
if( tsbkMessage2.isLastBlock() )
|
||||
/* Remove trellis encoding - abort processing if we have an
|
||||
* unsuccessful decode due to excessive errors */
|
||||
if( mHalfRate.decode( mMessage, TSBK_BEGIN, TSBK_END ) )
|
||||
{
|
||||
mComplete = true;
|
||||
BitSetBuffer tsbkBuffer2 = mMessage.copy();
|
||||
tsbkBuffer2.setSize( TSBK_DECODED_END );
|
||||
|
||||
TSBKMessage tsbkMessage2 = TSBKMessageFactory.getMessage(
|
||||
tsbkBuffer2, DataUnitID.TSBK2, mAliasList );
|
||||
|
||||
if( tsbkMessage2.isLastBlock() )
|
||||
{
|
||||
mComplete = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
setDUID( DataUnitID.TSBK3 );
|
||||
mMessage.setPointer( TSBK_BEGIN );
|
||||
}
|
||||
|
||||
dispatch( tsbkMessage2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
setDUID( DataUnitID.TSBK3 );
|
||||
mMessage.setPointer( TSBK_BEGIN );
|
||||
mComplete = true;
|
||||
}
|
||||
|
||||
dispatch( tsbkMessage2 );
|
||||
|
||||
break;
|
||||
case TSBK3:
|
||||
/* Remove interleaving */
|
||||
P25Interleave.deinterleave( mMessage, TSBK_BEGIN, TSBK_END );
|
||||
|
||||
/* Remove trellis encoding */
|
||||
mHalfRate.decode( mMessage, TSBK_BEGIN, TSBK_END );
|
||||
/* Remove trellis encoding - abort processing if we have an
|
||||
* unsuccessful decode due to excessive errors */
|
||||
if( mHalfRate.decode( mMessage, TSBK_BEGIN, TSBK_END ) )
|
||||
{
|
||||
BitSetBuffer tsbkBuffer3 = mMessage.copy();
|
||||
tsbkBuffer3.setSize( TSBK_DECODED_END );
|
||||
|
||||
TSBKMessage tsbkMessage3 = TSBKMessageFactory.getMessage(
|
||||
tsbkBuffer3, DataUnitID.TSBK3, mAliasList );
|
||||
|
||||
BitSetBuffer tsbkBuffer3 = mMessage.copy();
|
||||
tsbkBuffer3.setSize( TSBK_DECODED_END );
|
||||
|
||||
TSBKMessage tsbkMessage3 = TSBKMessageFactory.getMessage(
|
||||
tsbkBuffer3, DataUnitID.TSBK3, mAliasList );
|
||||
dispatch( tsbkMessage3 );
|
||||
}
|
||||
|
||||
mComplete = true;
|
||||
|
||||
dispatch( tsbkMessage3 );
|
||||
|
||||
break;
|
||||
case UNKN:
|
||||
mComplete = true;
|
||||
|
||||
Reference in New Issue
Block a user