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(toString());
return sb.toString();
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append( " ID:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() );
sb.append( " BANDWIDTH:" + 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;
}
}
@Override
public long getDownlinkFrequency(int channelNumber)
{
if(isTDMA())
{
return getBaseFrequency() + ( (channelNumber / getChannelType().getSlotsPerCarrier()) * getChannelSpacing() );
}
else
{
return super.getDownlinkFrequency(channelNumber);
}
}
@Override
public boolean isTDMA()
{
return getChannelType().getAccessType() == AccessType.TDMA;
}
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();
if( this.equals( TYPE_5 ) )
{
sb.append("H-D8PSK SIMULCAST " );
}
sb.append( mAccessType.name() );
sb.append( " BANDWIDTH:" + mBandwidth );
sb.append( " TIMESLOTS PER 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;
}
}