diff --git a/src/module/decode/p25/message/tsbk/TSBKMessageFactory.java b/src/module/decode/p25/message/tsbk/TSBKMessageFactory.java index e06ac784..3e8ab315 100644 --- a/src/module/decode/p25/message/tsbk/TSBKMessageFactory.java +++ b/src/module/decode/p25/message/tsbk/TSBKMessageFactory.java @@ -1,5 +1,7 @@ package module.decode.p25.message.tsbk; +import alias.AliasList; +import bits.BinaryMessage; import module.decode.p25.message.tsbk.motorola.ControlChannelBaseStationIdentification; import module.decode.p25.message.tsbk.motorola.MotorolaOpcode; import module.decode.p25.message.tsbk.motorola.MotorolaTSBKMessage; @@ -19,6 +21,7 @@ import module.decode.p25.message.tsbk.osp.control.ExtendedFunctionCommand; import module.decode.p25.message.tsbk.osp.control.GroupAffiliationQuery; import module.decode.p25.message.tsbk.osp.control.GroupAffiliationResponse; import module.decode.p25.message.tsbk.osp.control.IdentifierUpdateNonVUHF; +import module.decode.p25.message.tsbk.osp.control.IdentifierUpdateTDMA; import module.decode.p25.message.tsbk.osp.control.IdentifierUpdateVUHF; import module.decode.p25.message.tsbk.osp.control.LocationRegistrationResponse; import module.decode.p25.message.tsbk.osp.control.MessageUpdate; @@ -56,8 +59,6 @@ import module.decode.p25.message.tsbk.osp.voice.UnitToUnitVoiceChannelGrantUpdat import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Vendor; -import alias.AliasList; -import bits.BinaryMessage; public class TSBKMessageFactory { @@ -119,6 +120,8 @@ public class TSBKMessageFactory case IDENTIFIER_UPDATE_NON_VUHF: return new IdentifierUpdateNonVUHF( message, duid, aliasList ); + case IDENTIFIER_UPDATE_TDMA: + return new IdentifierUpdateTDMA( message, duid, aliasList ); case IDENTIFIER_UPDATE_VHF_UHF_BANDS: return new IdentifierUpdateVUHF( message, duid, aliasList ); diff --git a/src/module/decode/p25/message/tsbk/osp/control/IdentifierUpdateTDMA.java b/src/module/decode/p25/message/tsbk/osp/control/IdentifierUpdateTDMA.java new file mode 100644 index 00000000..e2189ef0 --- /dev/null +++ b/src/module/decode/p25/message/tsbk/osp/control/IdentifierUpdateTDMA.java @@ -0,0 +1,153 @@ +package module.decode.p25.message.tsbk.osp.control; + +import module.decode.p25.reference.DataUnitID; +import module.decode.p25.reference.Opcode; +import alias.AliasList; +import bits.BinaryMessage; + +public class IdentifierUpdateTDMA extends IdentifierUpdate +{ + public static final int[] CHANNEL_TYPE = { 84,85,86,87 }; + public static final int TRANSMIT_OFFSET_SIGN = 88; + public static final int[] TRANSMIT_OFFSET = { 89,90,91,92,93,94,95,96,97,98, + 99,100,101 }; + + public IdentifierUpdateTDMA( BinaryMessage message, + DataUnitID duid, + AliasList aliasList ) + { + super( message, duid, aliasList ); + } + + @Override + public String getEventType() + { + return Opcode.IDENTIFIER_UPDATE_TDMA.getDescription(); + } + + public String getMessage() + { + StringBuilder sb = new StringBuilder(); + + sb.append( getMessageStub() ); + + sb.append( " IDEN:" + getIdentifier() ); + sb.append( " BASE:" + getBaseFrequency() ); + sb.append( " BW:" + getBandwidth() ); + sb.append( " SPACING:" + getChannelSpacing() ); + sb.append( " OFFSET:" + getTransmitOffset() ); + sb.append( " TYPE:" + getChannelType().toString() ); + + return sb.toString(); + } + + public ChannelType getChannelType() + { + return ChannelType.fromValue( mMessage.getInt( CHANNEL_TYPE) ); + } + + /** + * Channel bandwidth in hertz + */ + public int getBandwidth() + { + return getChannelType().getBandwidth(); + } + + /** + * Transmit offset in hertz + */ + @Override + public long getTransmitOffset() + { + long offset = mMessage.getLong( TRANSMIT_OFFSET ) * + getChannelSpacing(); + + if( mMessage.get( TRANSMIT_OFFSET_SIGN ) ) + { + return offset; + } + else + { + return -offset; + } + } + + public enum ChannelType + { + TYPE_0( AccessType.FDMA, 12500, 1, Vocoder.HALF_RATE ), + TYPE_1( AccessType.FDMA, 12500, 1, Vocoder.FULL_RATE ), + TYPE_2( AccessType.FDMA, 6250, 1, Vocoder.HALF_RATE ), + TYPE_3( AccessType.TDMA, 12500, 2, Vocoder.HALF_RATE ), + TYPE_4( AccessType.TDMA, 25000, 4, Vocoder.HALF_RATE ), + TYPE_5( AccessType.TDMA, 12500, 2, Vocoder.HALF_RATE ), //HD8PSK simulcast + UNKNOWN( AccessType.UNKNOWN, 0, 0, Vocoder.HALF_RATE ); + + private AccessType mAccessType; + private int mBandwidth; + private int mSlotsPerCarrier; + private Vocoder mVocoder; + + private ChannelType( AccessType accessType, + int bandwidth, + int slots, + Vocoder vocoder ) + { + mAccessType = accessType; + mBandwidth = bandwidth; + mSlotsPerCarrier = slots; + mVocoder = vocoder; + } + + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append( mAccessType.name() ); + sb.append( " BW:" + mBandwidth ); + sb.append( " SLOT/CARRIER:" + mSlotsPerCarrier ); + sb.append( " VOCODER:" + mVocoder.name() ); + + return sb.toString(); + } + + public static ChannelType fromValue( int value ) + { + if( 0 <= value && value <= 5 ) + { + return ChannelType.values()[ value ]; + } + + return ChannelType.UNKNOWN; + } + + public AccessType getAccessType() + { + return mAccessType; + } + + public int getBandwidth() + { + return mBandwidth; + } + + public int getSlotsPerCarrier() + { + return mSlotsPerCarrier; + } + + public Vocoder getVocoder() + { + return mVocoder; + } + } + + public enum AccessType + { + FDMA,TDMA,UNKNOWN; + } + + public enum Vocoder + { + HALF_RATE, FULL_RATE; + } +} diff --git a/src/module/decode/p25/reference/Opcode.java b/src/module/decode/p25/reference/Opcode.java index 4dbf8870..d94afec8 100644 --- a/src/module/decode/p25/reference/Opcode.java +++ b/src/module/decode/p25/reference/Opcode.java @@ -53,7 +53,7 @@ public enum Opcode TDMA_SYNC_BROADCAST( "TDMA_SYNC_BCST ", "FDMA-TDMA Sync Broadcast", 48 ), RESERVED_31( "RESERVED_31 ", "Reserved", 49 ), RESERVED_32( "RESERVED_32 ", "Reserved", 50 ), - RESERVED_33( "RESERVED_33 ", "Reserved", 51 ), + IDENTIFIER_UPDATE_TDMA( "IDEN_UPDATE_TDMA", "Identifier Update for TDMA", 51 ), IDENTIFIER_UPDATE_VHF_UHF_BANDS( "IDEN_UPDATE_VUHF", "Identifier Update for VHF/UHF Bands", 52 ), TIME_DATE_ANNOUNCEMENT( "TIME_DATE_ANNOUN", "Time and Date Announcement", 53 ), ROAMING_ADDRESS_COMMAND( "ROAM_ADDR_CMD ", "Roaming Address Command", 54 ),