From f99ab161ff508f8f5c6b978856d011d4b3e17dda Mon Sep 17 00:00:00 2001 From: "dennis.sheirer" Date: Wed, 7 Jan 2015 02:15:06 +0000 Subject: [PATCH] Adds support for experimental Tait-1200 FFSK auxiliary decoder --- src/bits/SyncPattern.java | 19 +- src/controller/state/ChannelState.java | 11 + src/decode/DecoderFactory.java | 11 +- src/decode/DecoderType.java | 9 +- src/decode/tait/Tait1200ActivitySummary.java | 60 +++++ src/decode/tait/Tait1200CallEvent.java | 137 ++++++++++ src/decode/tait/Tait1200ChannelState.java | 63 +++++ src/decode/tait/Tait1200Decoder.java | 206 +++++++++++++++ src/decode/tait/Tait1200MessageA.java | 246 ++++++++++++++++++ .../tait/Tait1200MessageAProcessor.java | 64 +++++ src/decode/tait/Tait1200MessageB.java | 184 +++++++++++++ .../tait/Tait1200MessageBProcessor.java | 64 +++++ src/decode/tait/Tait1200MessageFilter.java | 35 +++ src/decode/tait/Tait1200Panel.java | 84 ++++++ src/instrument/gui/WaveSourceFrame.java | 4 + 15 files changed, 1192 insertions(+), 5 deletions(-) create mode 100644 src/decode/tait/Tait1200ActivitySummary.java create mode 100644 src/decode/tait/Tait1200CallEvent.java create mode 100644 src/decode/tait/Tait1200ChannelState.java create mode 100644 src/decode/tait/Tait1200Decoder.java create mode 100644 src/decode/tait/Tait1200MessageA.java create mode 100644 src/decode/tait/Tait1200MessageAProcessor.java create mode 100644 src/decode/tait/Tait1200MessageB.java create mode 100644 src/decode/tait/Tait1200MessageBProcessor.java create mode 100644 src/decode/tait/Tait1200MessageFilter.java create mode 100644 src/decode/tait/Tait1200Panel.java diff --git a/src/bits/SyncPattern.java b/src/bits/SyncPattern.java index 7ad876a6..c00abe25 100644 --- a/src/bits/SyncPattern.java +++ b/src/bits/SyncPattern.java @@ -148,7 +148,24 @@ public enum SyncPattern LTR_STANDARD_ISW( new boolean[] { false, true, false, true,false, false, true, true, true - } ); + } ), + + TAIT_MESSAGE_A( new boolean[] + { + true,false,true,false, + false,false,false,true, + false,true,false,false, + true,true,false,true, + true,true,false,false + }), + TAIT_MESSAGE_B( new boolean[] + { +// true,false,true,false, + false,false,false,false, + true,true,false,false, + false,true,true,true, + false,true,true,true + }); boolean[] mBits; diff --git a/src/controller/state/ChannelState.java b/src/controller/state/ChannelState.java index 23f4dac5..54327f51 100644 --- a/src/controller/state/ChannelState.java +++ b/src/controller/state/ChannelState.java @@ -597,6 +597,17 @@ public abstract class ChannelState implements Listener state == FADE; } }, + ENCRYPTED( "ENCRYPTED" ) + { + @Override + public boolean canChangeTo( State state ) + { + return state == CALL || + state == CONTROL || + state == DATA || + state == FADE; + } + }, CONTROL( "CONTROL" ) { @Override diff --git a/src/decode/DecoderFactory.java b/src/decode/DecoderFactory.java index b1c7f6b4..41fd789a 100644 --- a/src/decode/DecoderFactory.java +++ b/src/decode/DecoderFactory.java @@ -47,6 +47,8 @@ import decode.p25.P25ChannelState; import decode.p25.P25Decoder; import decode.passport.PassportChannelState; import decode.passport.PassportDecoder; +import decode.tait.Tait1200ChannelState; +import decode.tait.Tait1200Decoder; public class DecoderFactory { @@ -125,6 +127,11 @@ public class DecoderFactory case LJ_1200: retVal.addAuxiliaryDecoder( new LJ1200Decoder( aliasList ) ); + break; + case TAIT_1200: + retVal.addAuxiliaryDecoder( + new Tait1200Decoder( aliasList ) ); + break; } } } @@ -196,7 +203,9 @@ public class DecoderFactory retVal.addAuxChannelState( new MDCChannelState( retVal ) ); break; - + case TAIT_1200: + retVal.addAuxChannelState( + new Tait1200ChannelState( retVal ) ); } } } diff --git a/src/decode/DecoderType.java b/src/decode/DecoderType.java index 844360e4..92a69710 100644 --- a/src/decode/DecoderType.java +++ b/src/decode/DecoderType.java @@ -41,7 +41,8 @@ public enum DecoderType NBFM( "NBFM", "NBFM", "images/fm.png", 12500 ), PASSPORT( "Passport", "Passport", "images/passport.png", 12500 ), P25_PHASE1( "P25 Phase I", "P25-1", "images/p25_1.png", 12500 ), - P25_PHASE2( "P25 Phase II", "P25-2", "images/p25_2.png", 15000 ); + P25_PHASE2( "P25 Phase II", "P25-2", "images/p25_2.png", 15000 ), + TAIT_1200( "Tait 1200", "Tait 1200", "images/tait.png", 12500 ); private String mDisplayString; private String mShortDisplayString; @@ -67,7 +68,7 @@ public enum DecoderType DecoderType.LTR_STANDARD, DecoderType.MPT1327, DecoderType.NBFM, - DecoderType.P25_PHASE1, +// DecoderType.P25_PHASE1, DecoderType.PASSPORT ); } @@ -82,7 +83,8 @@ public enum DecoderType DecoderType.MDC1200, DecoderType.MPT1327, DecoderType.PASSPORT, - DecoderType.P25_PHASE1 ); + DecoderType.P25_PHASE1, + DecoderType.TAIT_1200 ); } /** @@ -95,6 +97,7 @@ public enum DecoderType decoders.add( DecoderType.FLEETSYNC2 ); decoders.add( DecoderType.LJ_1200 ); decoders.add( DecoderType.MDC1200 ); + decoders.add( DecoderType.TAIT_1200 ); return decoders; } diff --git a/src/decode/tait/Tait1200ActivitySummary.java b/src/decode/tait/Tait1200ActivitySummary.java new file mode 100644 index 00000000..a57e5f85 --- /dev/null +++ b/src/decode/tait/Tait1200ActivitySummary.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package decode.tait; + +import message.Message; +import sample.Listener; +import alias.AliasList; +import controller.activity.ActivitySummaryProvider; + +public class Tait1200ActivitySummary implements ActivitySummaryProvider, + Listener +{ + private AliasList mAliasList; + + public Tait1200ActivitySummary( AliasList list ) + { + mAliasList = list; + } + + public void dispose() + { + } + + @Override + public void receive( Message message ) + { + if( message instanceof Tait1200MessageA ) + { + Tait1200MessageA tait = ((Tait1200MessageA)message); + + //Do something here in the future + } + } + + @Override + public String getSummary() + { + StringBuilder sb = new StringBuilder(); + + sb.append( "=============================\n" ); + sb.append( "Decoder:\tTait-1200I\n\n" ); + + return sb.toString(); + } +} diff --git a/src/decode/tait/Tait1200CallEvent.java b/src/decode/tait/Tait1200CallEvent.java new file mode 100644 index 00000000..38f4aef8 --- /dev/null +++ b/src/decode/tait/Tait1200CallEvent.java @@ -0,0 +1,137 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package decode.tait; + +import alias.Alias; +import alias.AliasList; +import controller.activity.CallEvent; +import decode.DecoderType; + +public class Tait1200CallEvent extends CallEvent +{ + public Tait1200CallEvent( CallEventType callEventType, + AliasList aliasList, + String fromID, + String toID, + String details ) + { + super( DecoderType.TAIT_1200, callEventType, + aliasList, fromID, toID, details ); + } + + private Alias getAlias( String ident ) + { + if( hasAliasList() ) + { + return getAliasList().getFleetsyncAlias( ident ); + } + + return null; + } + + @Override + public Alias getFromIDAlias() + { + return getAlias( getFromID() ); + } + + @Override + public Alias getToIDAlias() + { + return getAlias( getToID() ); + } + + @Override + public String getChannel() + { + return null; + } + + @Override + public long getFrequency() + { + return 0; + } + + public static class Builder + { + /* Required parameters */ + private CallEventType mCallEventType; + + /* Optional parameters */ + private AliasList mAliasList; + private String mFromID; + private String mToID; + private String mDetails; + + public Builder( CallEventType callEventType ) + { + mCallEventType = callEventType; + } + + public Builder aliasList( AliasList aliasList ) + { + mAliasList = aliasList; + return this; + } + + public Builder from( String val ) + { + mFromID = val; + return this; +} + + public Builder details( String details ) + { + mDetails = details; + return this; + } + + public Builder to( String toID ) + { + mToID = toID; + return this; + } + + public Tait1200CallEvent build() + { + return new Tait1200CallEvent( this ); + } + } + + /** + * Private constructor for the builder + */ + private Tait1200CallEvent( Builder builder ) + { + this( builder.mCallEventType, + builder.mAliasList, + builder.mFromID, + builder.mToID, + builder.mDetails ); + } + + public static Tait1200CallEvent getLJ1200Event( Tait1200MessageA message ) + { + CallEventType type = CallEventType.COMMAND; + + return new Tait1200CallEvent.Builder( type ) + .details( message.getMessage() ) + .build(); + } +} diff --git a/src/decode/tait/Tait1200ChannelState.java b/src/decode/tait/Tait1200ChannelState.java new file mode 100644 index 00000000..06a148e9 --- /dev/null +++ b/src/decode/tait/Tait1200ChannelState.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package decode.tait; + +import message.Message; +import controller.state.AuxChannelState; +import controller.state.ChannelState; + +public class Tait1200ChannelState extends AuxChannelState +{ + private Tait1200ActivitySummary mActivitySummary; + + public Tait1200ChannelState( ChannelState parentState ) + { + super( parentState ); + + mActivitySummary = + new Tait1200ActivitySummary( parentState.getAliasList() ); + } + + @Override + public void reset() + { + } + + @Override + public void fade() + { + } + + @Override + public void receive( Message message ) + { + if( message instanceof Tait1200MessageA ) + { + mActivitySummary.receive( message ); + +// mParentChannelState.receiveCallEvent( +// Tait1200CallEvent.getLJ1200Event( (Tait1200Message)message ) ); + } + } + + @Override + public String getActivitySummary() + { + return mActivitySummary.getSummary(); + } +} diff --git a/src/decode/tait/Tait1200Decoder.java b/src/decode/tait/Tait1200Decoder.java new file mode 100644 index 00000000..75dafb59 --- /dev/null +++ b/src/decode/tait/Tait1200Decoder.java @@ -0,0 +1,206 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package decode.tait; + +import instrument.Instrumentable; +import instrument.tap.Tap; +import instrument.tap.stream.BinaryTap; +import instrument.tap.stream.FloatTap; + +import java.util.ArrayList; +import java.util.List; + +import sample.Broadcaster; +import sample.real.RealSampleListener; +import source.Source.SampleType; +import alias.AliasList; +import bits.MessageFramer; +import bits.SyncPattern; +import decode.Decoder; +import decode.DecoderType; +import dsp.filter.Filters; +import dsp.filter.FloatFIRFilter; +import dsp.filter.FloatHalfBandFilter; +import dsp.fsk.FSK2Decoder; +import dsp.fsk.FSK2Decoder.Output; + +/** + * TAIT 1200 - 1200 baud 2FSK decoder + */ +public class Tait1200Decoder extends Decoder implements Instrumentable +{ + /* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */ + private static final int DECIMATED_SAMPLE_RATE = 24000; + + /* Baud or Symbol Rate */ + private static final int SYMBOL_RATE = 1200; + + /* Message length ... */ + private static final int MESSAGE_LENGTH = 440; + + /* Instrumentation Taps */ + private ArrayList mAvailableTaps; + private static final String INSTRUMENT_INPUT = + "Tap Point: Float Input"; + private static final String INSTRUMENT_BANDPASS_FILTER_TO_FSK2_DEMOD = + "Tap Point: Bandpass Filter > < FSK2 Decoder"; + private static final String INSTRUMENT_FSK2_DECODER_TO_MESSAGE_FRAMER = + "Tap Point: FSK2 Decoder > < Message Framer"; + + private FSK2Decoder mFSKDecoder; + + private FloatHalfBandFilter mDecimationFilter; + private FloatFIRFilter mBandPassFilter; + private MessageFramer mMessageFramerA; + private MessageFramer mMessageFramerB; + private Broadcaster mFSKBroadcaster = new Broadcaster(); + private Tait1200MessageAProcessor mMessageAProcessor; + private Tait1200MessageBProcessor mMessageBProcessor; + + public Tait1200Decoder( AliasList aliasList ) + { + super( SampleType.REAL ); + + mDecimationFilter = new FloatHalfBandFilter( + Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 ); + addRealSampleListener( mDecimationFilter ); + + mBandPassFilter = new FloatFIRFilter( + Filters.FIRBP_1200FSK_24000FS.getCoefficients(), 1.02 ); + mDecimationFilter.setListener( mBandPassFilter ); + + mFSKDecoder = new FSK2Decoder( DECIMATED_SAMPLE_RATE, + SYMBOL_RATE, Output.INVERTED ); + mBandPassFilter.setListener( mFSKDecoder ); + + + mFSKDecoder.setListener( mFSKBroadcaster ); + + mMessageFramerA = new MessageFramer( + SyncPattern.TAIT_MESSAGE_A.getPattern(), MESSAGE_LENGTH ); + mMessageFramerB = new MessageFramer( + SyncPattern.TAIT_MESSAGE_B.getPattern(), MESSAGE_LENGTH ); + + mFSKBroadcaster.addListener( mMessageFramerA ); + mFSKBroadcaster.addListener( mMessageFramerB ); + + mMessageAProcessor = new Tait1200MessageAProcessor( aliasList ); + mMessageBProcessor = new Tait1200MessageBProcessor( aliasList ); + + mMessageFramerA.addMessageListener( mMessageAProcessor ); + mMessageFramerB.addMessageListener( mMessageBProcessor ); + + mMessageAProcessor.addMessageListener( this ); + mMessageBProcessor.addMessageListener( this ); + } + + public void dispose() + { + super.dispose(); + + mDecimationFilter.dispose(); + mBandPassFilter.dispose(); + mFSKDecoder.dispose(); + mMessageFramerA.dispose(); + mMessageFramerB.dispose(); + mMessageAProcessor.dispose(); + mMessageBProcessor.dispose(); + } + + @Override + public DecoderType getType() + { + return DecoderType.TAIT_1200; + } + + /** + * Returns a float listener interface for connecting this decoder to a + * float stream provider + */ + public RealSampleListener getRealReceiver() + { + return (RealSampleListener)mDecimationFilter; + } + + @Override + public List getTaps() + { + if( mAvailableTaps == null ) + { + mAvailableTaps = new ArrayList(); + + mAvailableTaps.add( new FloatTap( INSTRUMENT_INPUT, 0, 1.0f ) ); + mAvailableTaps.add( new FloatTap( + INSTRUMENT_BANDPASS_FILTER_TO_FSK2_DEMOD, 0, 0.5f ) ); + mAvailableTaps.addAll( mFSKDecoder.getTaps() ); + mAvailableTaps.add( new BinaryTap( + INSTRUMENT_FSK2_DECODER_TO_MESSAGE_FRAMER, 0, 0.025f ) ); + } + + return mAvailableTaps; + } + + @Override + public void addTap( Tap tap ) + { + mFSKDecoder.addTap( tap ); + + switch( tap.getName() ) + { + case INSTRUMENT_INPUT: + FloatTap inputTap = (FloatTap)tap; + addRealSampleListener( inputTap ); + break; + case INSTRUMENT_BANDPASS_FILTER_TO_FSK2_DEMOD: + FloatTap bpTap = (FloatTap)tap; + mBandPassFilter.setListener( bpTap ); + bpTap.setListener( mFSKDecoder ); + break; + case INSTRUMENT_FSK2_DECODER_TO_MESSAGE_FRAMER: + BinaryTap decoderTap = (BinaryTap)tap; + mFSKBroadcaster.addListener( decoderTap ); + break; + } + } + + @Override + public void removeTap( Tap tap ) + { + mFSKDecoder.removeTap( tap ); + + switch( tap.getName() ) + { + case INSTRUMENT_INPUT: + FloatTap inputTap = (FloatTap)tap; + removeRealListener( inputTap ); + break; + case INSTRUMENT_BANDPASS_FILTER_TO_FSK2_DEMOD: + mBandPassFilter.setListener( mFSKDecoder ); + break; + case INSTRUMENT_FSK2_DECODER_TO_MESSAGE_FRAMER: + mFSKBroadcaster.removeListener( (BinaryTap)tap ); + break; + } + } + + @Override + public void addUnfilteredRealSampleListener( RealSampleListener listener ) + { + //Not implemented + } +} diff --git a/src/decode/tait/Tait1200MessageA.java b/src/decode/tait/Tait1200MessageA.java new file mode 100644 index 00000000..270d040f --- /dev/null +++ b/src/decode/tait/Tait1200MessageA.java @@ -0,0 +1,246 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package decode.tait; + +import java.text.SimpleDateFormat; + +import map.Plottable; +import message.Message; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import alias.Alias; +import alias.AliasList; +import bits.BitSetBuffer; +import edac.CRC; + +public class Tait1200MessageA extends Message +{ + private final static Logger mLog = LoggerFactory.getLogger( Tait1200MessageA.class ); + + public static int[] REVS_1 = { 0,1,2,3 }; + public static int[] SYNC = { 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 }; + public static int[] SIZE = { 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35 }; + public static int[] FROM_DIGIT_1 = { 36,37,38,39,40,41,42,43 }; + public static int[] FROM_DIGIT_2 = { 44,45,46,47,48,49,50,51 }; + public static int[] FROM_DIGIT_3 = { 52,53,54,55,56,57,58,59 }; + public static int[] FROM_DIGIT_4 = { 60,61,62,63,64,65,66,67 }; + public static int[] FROM_DIGIT_5 = { 68,69,70,71,72,73,74,75 }; + public static int[] FROM_DIGIT_6 = { 76,77,78,79,80,81,82,83 }; + public static int[] FROM_DIGIT_7 = { 84,85,86,87,88,89,90,91 }; + public static int[] FROM_DIGIT_8 = { 92,93,94,95,96,97,98,99 }; + public static int[] CHECKSUM_1 = { 100,101,102,103,104,105,106,107,108,109, + 110,111,112,113,114,115 }; + public static int[] REVS_2 = { 116,117,118,119,120,121,122,123,124,125,126,127, + 128,129,130,131 }; + + public static int[] SIZE_2 = { 188,189,190,191,192,193,194,195,196,197,198, + 199,200,201,202,203 }; + public static int[] TO_DIGIT_1 = { 204,205,206,207,208,209,210,211 }; + public static int[] TO_DIGIT_2 = { 212,213,214,215,216,217,218,219 }; + public static int[] TO_DIGIT_3 = { 220,221,222,223,224,225,226,227 }; + public static int[] TO_DIGIT_4 = { 228,229,230,231,232,233,234,235 }; + public static int[] TO_DIGIT_5 = { 236,237,238,239,240,241,242,243 }; + public static int[] TO_DIGIT_6 = { 244,245,246,247,248,249,250,251 }; + public static int[] TO_DIGIT_7 = { 252,253,254,255,256,257,258,259 }; + public static int[] TO_DIGIT_8 = { 260,261,262,263,264,265,266,267 }; + + private static SimpleDateFormat mSDF = new SimpleDateFormat( "yyyyMMdd HHmmss" ); + + private BitSetBuffer mMessage; + private AliasList mAliasList; + private CRC mCRC; + + public Tait1200MessageA( BitSetBuffer message, AliasList list ) + { + mMessage = message; + mAliasList = list; + } + + public boolean isValid() + { + //TODO: Override until we figure out the CRC + return true; + } + + public int getMessage1Size() + { + return mMessage.getInt( SIZE ); + } + + public int getMessage2Size() + { + return mMessage.getInt( SIZE_2 ); + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + + sb.append( "TAIT MESSAGE A FROM:" ); + sb.append( getFromID() ); + sb.append( " TO:" ); + sb.append( getToID() ); + sb.append( " SIZES:" ); + sb.append( getMessage1Size() ); + sb.append( "/" ); + sb.append( getMessage2Size() ); + sb.append( " " ); + sb.append( mMessage.toString() ); + + return sb.toString(); + } + + @Override + public String getFromID() + { + StringBuilder sb = new StringBuilder(); + + sb.append( getCharacter( FROM_DIGIT_1 ) ); + sb.append( getCharacter( FROM_DIGIT_2 ) ); + sb.append( getCharacter( FROM_DIGIT_3 ) ); + sb.append( getCharacter( FROM_DIGIT_4 ) ); + sb.append( getCharacter( FROM_DIGIT_5 ) ); + sb.append( getCharacter( FROM_DIGIT_6 ) ); + sb.append( getCharacter( FROM_DIGIT_7 ) ); + sb.append( getCharacter( FROM_DIGIT_8 ) ); + + return sb.toString(); + } + + @Override + public Alias getFromIDAlias() + { + if( mAliasList != null ) + { + return mAliasList.getTalkgroupAlias( getFromID() ); + } + + return null; + } + + @Override + public String getToID() + { + StringBuilder sb = new StringBuilder(); + + sb.append( getCharacter( TO_DIGIT_1 ) ); + sb.append( getCharacter( TO_DIGIT_2 ) ); + sb.append( getCharacter( TO_DIGIT_3 ) ); + sb.append( getCharacter( TO_DIGIT_4 ) ); + sb.append( getCharacter( TO_DIGIT_5 ) ); + sb.append( getCharacter( TO_DIGIT_6 ) ); + sb.append( getCharacter( TO_DIGIT_7 ) ); + sb.append( getCharacter( TO_DIGIT_8 ) ); + + return sb.toString(); + } + + @Override + public Alias getToIDAlias() + { + if( mAliasList != null ) + { + return mAliasList.getTalkgroupAlias( getToID() ); + } + + return null; + } + + public char getCharacter( int[] bits ) + { + int value = mMessage.getInt( bits ); + + return (char)value; + } + + /** + * Pads spaces onto the end of the value to make it 'places' long + */ + public String pad( String value, int places, String padCharacter ) + { + StringBuilder sb = new StringBuilder(); + + sb.append( value ); + + while( sb.length() < places ) + { + sb.append( padCharacter ); + } + + return sb.toString(); + } + + /** + * Pads an integer value with additional zeroes to make it decimalPlaces long + */ + public String format( int number, int decimalPlaces ) + { + StringBuilder sb = new StringBuilder(); + + int paddingRequired = decimalPlaces - ( String.valueOf( number ).length() ); + + for( int x = 0; x < paddingRequired; x++) + { + sb.append( "0" ); + } + + sb.append( number ); + + return sb.toString(); + } + + @Override + public String getBinaryMessage() + { + return mMessage.toString(); + } + + @Override + public String getProtocol() + { + return "Tait-1200"; + } + + @Override + public String getEventType() + { + return "Unknown"; + } + + @Override + public String getMessage() + { + return toString(); + } + + @Override + public String getErrorStatus() + { + return "UNKNOWN"; +// return mCRC.getDisplayText(); + } + + @Override + public Plottable getPlottable() + { + return null; + } +} diff --git a/src/decode/tait/Tait1200MessageAProcessor.java b/src/decode/tait/Tait1200MessageAProcessor.java new file mode 100644 index 00000000..10d2f02f --- /dev/null +++ b/src/decode/tait/Tait1200MessageAProcessor.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package decode.tait; + +import message.Message; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sample.Broadcaster; +import sample.Listener; +import alias.AliasList; +import bits.BitSetBuffer; + +public class Tait1200MessageAProcessor implements Listener +{ + private final static Logger mLog = + LoggerFactory.getLogger( Tait1200MessageAProcessor.class ); + + private Broadcaster mBroadcaster = new Broadcaster(); + + private AliasList mAliasList; + + public Tait1200MessageAProcessor( AliasList list ) + { + mAliasList = list; + } + + public void dispose() + { + mBroadcaster.dispose(); + } + + @Override + public void receive( BitSetBuffer buffer ) + { + mBroadcaster.receive( new Tait1200MessageA( buffer, mAliasList ) ); + } + + public void addMessageListener( Listener listener ) + { + mBroadcaster.addListener( listener ); + } + + public void removeMessageListener( Listener listener ) + { + mBroadcaster.removeListener( listener ); + } +} diff --git a/src/decode/tait/Tait1200MessageB.java b/src/decode/tait/Tait1200MessageB.java new file mode 100644 index 00000000..dab747a8 --- /dev/null +++ b/src/decode/tait/Tait1200MessageB.java @@ -0,0 +1,184 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package decode.tait; + +import java.text.SimpleDateFormat; + +import map.Plottable; +import message.Message; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import alias.Alias; +import alias.AliasList; +import bits.BitSetBuffer; +import edac.CRC; + +public class Tait1200MessageB extends Message +{ + private final static Logger mLog = LoggerFactory.getLogger( Tait1200MessageB.class ); + + public static int[] SYNC = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; + + private static SimpleDateFormat mSDF = new SimpleDateFormat( "yyyyMMdd HHmmss" ); + + private BitSetBuffer mMessage; + private AliasList mAliasList; + private CRC mCRC; + + public Tait1200MessageB( BitSetBuffer message, AliasList list ) + { + mMessage = message; + mAliasList = list; + +// checkCRC(); +// +// switch( mCRC ) +// { +// case CORRECTED: +// mLog.debug( "CORR:" + message.toString() ); +// break; +// case FAILED_CRC: +// mLog.debug( "FAIL:" + message.toString() ); +// break; +// case PASSED: +// mLog.debug( "PASS:" + message.toString() ); +// break; +// } + } + + private void checkCRC() + { +// mCRC = CRCLJ.checkAndCorrect( mMessage ); + } + + public boolean isValid() + { +// return mCRC == CRC.PASSED || mCRC == CRC.CORRECTED; + return true; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + + sb.append( "TAIT MESSAGE B " ); + sb.append( mMessage.toString() ); + + return sb.toString(); + } + + /** + * Pads spaces onto the end of the value to make it 'places' long + */ + public String pad( String value, int places, String padCharacter ) + { + StringBuilder sb = new StringBuilder(); + + sb.append( value ); + + while( sb.length() < places ) + { + sb.append( padCharacter ); + } + + return sb.toString(); + } + + /** + * Pads an integer value with additional zeroes to make it decimalPlaces long + */ + public String format( int number, int decimalPlaces ) + { + StringBuilder sb = new StringBuilder(); + + int paddingRequired = decimalPlaces - ( String.valueOf( number ).length() ); + + for( int x = 0; x < paddingRequired; x++) + { + sb.append( "0" ); + } + + sb.append( number ); + + return sb.toString(); + } + + @Override + public String getBinaryMessage() + { + return mMessage.toString(); + } + + @Override + public String getProtocol() + { + return "Tait-1200"; + } + + @Override + public String getEventType() + { + return "Unknown"; + } + + @Override + public String getFromID() + { + return null; + } + + @Override + public Alias getFromIDAlias() + { + return null; + } + + @Override + public String getToID() + { + return null; + } + + @Override + public Alias getToIDAlias() + { + return null; + } + + @Override + public String getMessage() + { + return toString(); + } + + @Override + public String getErrorStatus() + { + return "UNKNOWN"; +// return mCRC.getDisplayText(); + } + + @Override + public Plottable getPlottable() + { + return null; + } +} diff --git a/src/decode/tait/Tait1200MessageBProcessor.java b/src/decode/tait/Tait1200MessageBProcessor.java new file mode 100644 index 00000000..1babc692 --- /dev/null +++ b/src/decode/tait/Tait1200MessageBProcessor.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package decode.tait; + +import message.Message; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sample.Broadcaster; +import sample.Listener; +import alias.AliasList; +import bits.BitSetBuffer; + +public class Tait1200MessageBProcessor implements Listener +{ + private final static Logger mLog = + LoggerFactory.getLogger( Tait1200MessageBProcessor.class ); + + private Broadcaster mBroadcaster = new Broadcaster(); + + private AliasList mAliasList; + + public Tait1200MessageBProcessor( AliasList list ) + { + mAliasList = list; + } + + public void dispose() + { + mBroadcaster.dispose(); + } + + @Override + public void receive( BitSetBuffer buffer ) + { + mBroadcaster.receive( new Tait1200MessageB( buffer, mAliasList ) ); + } + + public void addMessageListener( Listener listener ) + { + mBroadcaster.addListener( listener ); + } + + public void removeMessageListener( Listener listener ) + { + mBroadcaster.removeListener( listener ); + } +} diff --git a/src/decode/tait/Tait1200MessageFilter.java b/src/decode/tait/Tait1200MessageFilter.java new file mode 100644 index 00000000..3e8b04d2 --- /dev/null +++ b/src/decode/tait/Tait1200MessageFilter.java @@ -0,0 +1,35 @@ +package decode.tait; + +import java.util.Collections; +import java.util.List; + +import message.Message; +import filter.Filter; +import filter.FilterElement; + +public class Tait1200MessageFilter extends Filter +{ + + public Tait1200MessageFilter() + { + super( "Tait-1200 Message Filter" ); + } + + @Override + public boolean passes( Message message ) + { + return mEnabled && canProcess( message ); + } + + @Override + public boolean canProcess( Message message ) + { + return message instanceof Tait1200MessageA; + } + + @Override + public List> getFilterElements() + { + return Collections.EMPTY_LIST; + } +} diff --git a/src/decode/tait/Tait1200Panel.java b/src/decode/tait/Tait1200Panel.java new file mode 100644 index 00000000..10db4912 --- /dev/null +++ b/src/decode/tait/Tait1200Panel.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package decode.tait; + +import javax.swing.JLabel; + +import net.miginfocom.swing.MigLayout; +import settings.ColorSetting; +import settings.ColorSetting.ColorSettingName; +import settings.Setting; +import settings.SettingsManager; +import controller.state.AuxStatePanel; +import controller.state.ChannelState.ChangedAttribute; + +public class Tait1200Panel extends AuxStatePanel +{ + private static final long serialVersionUID = 1L; + private static final String PROTOCOL = "TAIT-1200"; + + private JLabel mProtocol = new JLabel( PROTOCOL ); + + public Tait1200Panel( SettingsManager settingsManager, Tait1200ChannelState state ) + { + super( settingsManager, state ); + + init(); + } + + public void dispose() + { + super.dispose(); + } + + public Tait1200ChannelState getState() + { + return (Tait1200ChannelState)mAuxChannelState; + } + + private void init() + { + setOpaque( false ); //Use the parent panel's background color + + setLayout( new MigLayout( "insets 1 0 0 0", "[grow,fill]", "[]0[]0[]") ); + + addLabel( mProtocol, false ); + } + + @Override + public void receive( final ChangedAttribute changedAttribute ) + { + } + + @Override + public void settingChanged( Setting setting ) + { + super.settingChanged( setting ); + + if( setting instanceof ColorSetting ) + { + ColorSetting color = (ColorSetting)setting; + + if( color.getColorSettingName() == + ColorSettingName.CHANNEL_STATE_LABEL_AUX_DECODER ) + { + mProtocol.setForeground( color.getColor() ); + } + } + } +} diff --git a/src/instrument/gui/WaveSourceFrame.java b/src/instrument/gui/WaveSourceFrame.java index 9eec3dcc..b5205d00 100644 --- a/src/instrument/gui/WaveSourceFrame.java +++ b/src/instrument/gui/WaveSourceFrame.java @@ -53,6 +53,7 @@ import decode.mpt1327.MPT1327Decoder; import decode.mpt1327.MPT1327Decoder.Sync; import decode.p25.P25Decoder; import decode.passport.PassportDecoder; +import decode.tait.Tait1200Decoder; public class WaveSourceFrame extends JInternalFrame implements PositionListener { @@ -163,6 +164,9 @@ public class WaveSourceFrame extends JInternalFrame implements PositionListener case P25_PHASE1: decoder = new P25Decoder( SampleType.REAL, null ); break; + case TAIT_1200: + decoder = new Tait1200Decoder( null ); + break; } if( decoder != null )