mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Updates TDMA synchronization broadcast message to ICD
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package module.decode.p25.message.tsbk.osp.control;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import module.decode.p25.message.tsbk.TSBKMessage;
|
||||
@@ -12,20 +14,21 @@ import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
|
||||
/**
|
||||
* Sync Broadcast - used to broadcast FDMA-TDMA synchronization timestamp so
|
||||
* that a subscriber unit that is time synchronized on an FDMA control channel
|
||||
* is also synchronized with a TDMA traffic channel.
|
||||
* Sync Broadcast - used to broadcast FDMA-TDMA timing synchronization
|
||||
* information so that a subscriber unit that is time synchronized on an FDMA
|
||||
* control channel is also time synchronized with all TDMA traffic channels at
|
||||
* the site.
|
||||
*/
|
||||
public class SyncBroadcast extends TSBKMessage
|
||||
{
|
||||
public static final int US = 92;
|
||||
public static final int IST = 93;
|
||||
public static final int MMU = 94;
|
||||
public static final int[] MC = { 95,96 };
|
||||
public static final int VL = 97;
|
||||
public static final int[] RESERVED = { 80,81,82,83,84,85,86,87,88,89,90,91,92 };
|
||||
public static final int SYSTEM_TIME_NOT_LOCKED_TO_EXTERNAL_REFERENCE = 93;
|
||||
public static final int MICRO_SLOTS_TO_MINUTE_ROLLOVER_UNLOCKED = 94;
|
||||
public static final int[] LEAP_SECOND_CORRECTION = { 95,96 };
|
||||
public static final int LOCAL_TIME_OFFSET_VALID = 97;
|
||||
public static final int LOCAL_TIME_OFFSET_SIGN = 98;
|
||||
public static final int[] LOCAL_TIME_OFFSET = { 99,100,101,102 };
|
||||
public static final int LOCAL_TIME_OFFSET_HALF = 103;
|
||||
public static final int[] LOCAL_TIME_OFFSET_HOURS = { 99,100,101,102 };
|
||||
public static final int LOCAL_TIME_OFFSET_HALF_HOUR = 103;
|
||||
|
||||
public static final int[] YEAR = { 104,105,106,107,108,109,110 };
|
||||
public static final int[] MONTH = { 111,112,113,114 };
|
||||
@@ -36,7 +39,10 @@ public class SyncBroadcast extends TSBKMessage
|
||||
139,140,141,142,143 };
|
||||
public static final int[] TSBK_CRC = { 144,145,146,147,148,149,150,151,152,
|
||||
153,154,155,156,157,158,159 };
|
||||
|
||||
|
||||
private static final DateFormat TIME_FORMATTER = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS Z" );
|
||||
private static final TimeZone NO_TIME_ZONE = new SimpleTimeZone( 0, "NONE" );
|
||||
|
||||
public SyncBroadcast( BinaryMessage message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
@@ -56,24 +62,41 @@ public class SyncBroadcast extends TSBKMessage
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " " + new Date( getTime() ).toString() );
|
||||
sb.append( " TIME ZONE OFFSET:" + getTimeZone().toUpperCase() );
|
||||
sb.append( " US:" + isUS() );
|
||||
sb.append( " IST:" + isIST() );
|
||||
sb.append( " MMU:" + isMMU() );
|
||||
sb.append( " VL:" + isVL() );
|
||||
sb.append( " SYSTEM TIME" );
|
||||
|
||||
if( isSystemTimeNotLockedToExternalReference() )
|
||||
{
|
||||
sb.append( " UNLOCKED" );
|
||||
}
|
||||
|
||||
sb.append( ":" );
|
||||
|
||||
TIME_FORMATTER.setTimeZone( getTimeZone() );
|
||||
sb.append( " " + TIME_FORMATTER.format( new Date( getSystemTime() ) ) );
|
||||
|
||||
sb.append( " LEAP-SECOND CORRECTION:" + getLeapSecondCorrection() + "mS" );
|
||||
|
||||
if( isMicroslotsLockedToMinuteRollover() )
|
||||
{
|
||||
sb.append( " MICROSLOT-MINUTE ROLLOVER:LOCKED" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( " MICROSLOT-MINUTE ROLLOVER:UNLOCKED" );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time sync in java time (ie milliseconds since epoch )
|
||||
* System Time (UTC) in milliseconds since java epoch
|
||||
*/
|
||||
public long getTime()
|
||||
public long getSystemTime()
|
||||
{
|
||||
Calendar cal = new GregorianCalendar();
|
||||
Calendar cal = Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) );
|
||||
|
||||
cal.clear();
|
||||
cal.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
|
||||
|
||||
cal.set( Calendar.YEAR, getYear() );
|
||||
cal.set( Calendar.MONTH, getMonth() - 1 );
|
||||
cal.set( Calendar.DAY_OF_MONTH, getDay() );
|
||||
@@ -84,102 +107,165 @@ public class SyncBroadcast extends TSBKMessage
|
||||
return cal.getTimeInMillis();
|
||||
}
|
||||
|
||||
public boolean isUS()
|
||||
/**
|
||||
* System Time not locked to external time reference indicator
|
||||
*/
|
||||
public boolean isSystemTimeNotLockedToExternalReference()
|
||||
{
|
||||
return mMessage.get( US );
|
||||
return mMessage.get( SYSTEM_TIME_NOT_LOCKED_TO_EXTERNAL_REFERENCE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Daylight Savings Time
|
||||
* Micro-slot-to-Minute rollover boundary lock indicator.
|
||||
*
|
||||
* Note: we invert the message value so that true indicates that the micro
|
||||
* slots and minute rollovers are locked, whereas the ICD uses false to
|
||||
* indicate a lock.
|
||||
*
|
||||
* @return true if the microslots rollover at each minute interval is locked
|
||||
* to the system time minute rollover.
|
||||
*
|
||||
* @return false if the microslots and minutes rollover are not locked. This
|
||||
* indicates that the microslots minute rollover is free rolling.
|
||||
*
|
||||
*/
|
||||
public boolean isIST()
|
||||
public boolean isMicroslotsLockedToMinuteRollover()
|
||||
{
|
||||
return mMessage.get( IST );
|
||||
return !mMessage.get( MICRO_SLOTS_TO_MINUTE_ROLLOVER_UNLOCKED );
|
||||
}
|
||||
|
||||
/**
|
||||
* No idea ...
|
||||
* Leap second correction value that should be applied to the system time.
|
||||
*
|
||||
* The leap-second correction field indicates the number of 2.5 millisecond
|
||||
* units that must be added to the system time to account for the insertion
|
||||
* of leap seconds when the system time is represented as UTC universal time.
|
||||
*
|
||||
* @return leap-second correction value in milliseconds 0.0-10.0
|
||||
*/
|
||||
public boolean isMMU()
|
||||
public double getLeapSecondCorrection()
|
||||
{
|
||||
return mMessage.get( MMU );
|
||||
return (double)mMessage.getInt( LEAP_SECOND_CORRECTION ) * 2.5d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Indicates the local time offset fields contain valid information.
|
||||
*/
|
||||
public boolean isValidLocalTimeOffset()
|
||||
{
|
||||
return !mMessage.get( LOCAL_TIME_OFFSET_VALID );
|
||||
}
|
||||
|
||||
/**
|
||||
* Millenium ...?
|
||||
* Local time zone offset from UTC universal time (zulu) when the VALID
|
||||
* LOCAL TIME OFFSET flag indicates a valid offset. Otherwise, this method
|
||||
* returns a static +00:00 indicating no local time offset.
|
||||
*/
|
||||
public int getMC()
|
||||
public TimeZone getTimeZone()
|
||||
{
|
||||
return mMessage.getInt( MC );
|
||||
if( isValidLocalTimeOffset() )
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
offset += mMessage.getInt( LOCAL_TIME_OFFSET_HOURS ) * 3600000;
|
||||
offset += mMessage.get( LOCAL_TIME_OFFSET_HALF_HOUR ) ? 1800000 : 0;
|
||||
offset = mMessage.get( LOCAL_TIME_OFFSET_SIGN ) ? -offset : offset;
|
||||
|
||||
return new SimpleTimeZone( offset, "LOCAL" );
|
||||
}
|
||||
else
|
||||
{
|
||||
return NO_TIME_ZONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* No idea ....
|
||||
* System time - year.
|
||||
*
|
||||
* @return year in range 2000-2127
|
||||
*/
|
||||
public boolean isVL()
|
||||
{
|
||||
return mMessage.get( VL );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the time zone from the local time offset field.
|
||||
*/
|
||||
public String getTimeZone()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.get( LOCAL_TIME_OFFSET_SIGN ) ? "-" : "+" );
|
||||
|
||||
int hours = mMessage.getInt( LOCAL_TIME_OFFSET );
|
||||
sb.append( ( hours < 10 ? "0" : "" ) + String.valueOf( hours ) );
|
||||
|
||||
sb.append( ":" );
|
||||
|
||||
sb.append( mMessage.get( LOCAL_TIME_OFFSET_HALF ) ? "30" : "00" );
|
||||
|
||||
if( mMessage.get( IST ) )
|
||||
{
|
||||
sb.append( " DST" );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getYear()
|
||||
{
|
||||
return 2000 + mMessage.getInt( YEAR );
|
||||
}
|
||||
|
||||
/**
|
||||
* System time - month
|
||||
*
|
||||
* @return month 1-12 where 1=January and 12=December
|
||||
*/
|
||||
public int getMonth()
|
||||
{
|
||||
return mMessage.getInt( MONTH );
|
||||
}
|
||||
|
||||
/**
|
||||
* System time - day of month
|
||||
*
|
||||
* @return day of month in range 1-31
|
||||
*/
|
||||
public int getDay()
|
||||
{
|
||||
return mMessage.getInt( DAY );
|
||||
}
|
||||
|
||||
/**
|
||||
* System time - hours
|
||||
*
|
||||
* @return hours in range 0 - 23
|
||||
*/
|
||||
public int getHours()
|
||||
{
|
||||
return mMessage.getInt( HOURS );
|
||||
}
|
||||
|
||||
/**
|
||||
* System time - minutes
|
||||
*
|
||||
* @return minutes in range 0 - 59
|
||||
*/
|
||||
public int getMinutes()
|
||||
{
|
||||
return mMessage.getInt( MINUTES );
|
||||
}
|
||||
|
||||
/**
|
||||
* System time - milli-seconds
|
||||
*
|
||||
* Note: sub-millisecond values are rounded to nearest millisecond unit to
|
||||
* conform to java Date internal milli-second precision level.
|
||||
*
|
||||
* @return milli-seconds in range 0 - 59999;
|
||||
*/
|
||||
public int getMilliSeconds()
|
||||
{
|
||||
return (int)( (double)getMicroSlots() * 7.5 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Micro Slots - each uslot = 7.5 milliseconds. The value ranges 0 - 7999
|
||||
* and represents 60,000 milliseconds ( 8000 x 7.5 ms). Superframes occur
|
||||
* every 360 ms (48 micro-slots) on FDMA and Ultraframes occur every 4
|
||||
* super frames on TDMA.
|
||||
* TDMA Micro Slots.
|
||||
*
|
||||
* Number of 7.5 millisecond micro slots since the last minute rollover, or
|
||||
* since the last micro-slot counter rollover when the the micro-slot to
|
||||
* minute rollover is unlocked.
|
||||
*
|
||||
* @see isMicroslotsLockedToMinuteRollover() method.
|
||||
*
|
||||
* This value supports mobile subscriber timing alignment with a TDMA traffic
|
||||
* channel when a channel is granted from the control channels, so that when
|
||||
* the mobile changes from the control channel to the traffic channel, it is
|
||||
* already aligned with the traffic channel TDMA timing.
|
||||
*
|
||||
* Super frames occur every 360 ms (48 micro-slots) on FDMA and Ultra frames
|
||||
* occur every 4 super frames on TDMA.
|
||||
*
|
||||
* Valid micro-slot values range 0-7999 and represent 60,000
|
||||
* milliseconds ( 8000 x 7.5 ms).
|
||||
*
|
||||
* @return number of 7.5 mS micro-slots since last minute or micro-slot
|
||||
* rollover
|
||||
*/
|
||||
public int getMicroSlots()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user