@Override public List<Tap> getTaps() { if (mAvailableTaps == null) { mAvailableTaps = new ArrayList<Tap>(); if (mSourceSampleType == SampleType.COMPLEX) { if (mCQPSKDemodulator != null) { mAvailableTaps.addAll(mCQPSKDemodulator.getTaps()); } // mAvailableTaps.add( new ComplexTap( INSTRUMENT_COMPLEX_INPUT, 0, 1.0f ) ); // mAvailableTaps.add( new ComplexTap( INSTRUMENT_BASEBAND_FILTER_OUTPUT, 0, 1.0f ) ); } else { mAvailableTaps.add(new FloatTap(INSTRUMENT_REAL_INPUT, 0, 1.0f)); } if (mModulation == Modulation.C4FM) { mAvailableTaps.add(new FloatTap(INSTRUMENT_DGC_OUTPUT, 0, 1.0f)); mAvailableTaps.add(new FloatTap(INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT, 0, 0.1f)); mAvailableTaps.add(new DibitTap(INSTRUMENT_C4FM_SLICER_OUTPUT, 0, 0.1f)); if (mSymbolFilter != null) { mAvailableTaps.addAll(mSymbolFilter.getTaps()); } } else { mAvailableTaps.add(new ComplexTap(INSTRUMENT_AGC_OUTPUT, 0, 1.0f)); mAvailableTaps.add(new QPSKTap(INSTRUMENT_QPSK_DEMODULATOR_OUTPUT, 0, 1.0f)); mAvailableTaps.add(new DibitTap(INSTRUMENT_CQPSK_SLICER_OUTPUT, 0, 0.1f)); } } return mAvailableTaps; }
@Override public void removeTap(Tap tap) { if (mSymbolFilter != null) { mSymbolFilter.removeTap(tap); } if (mCQPSKDemodulator != null) { mCQPSKDemodulator.removeTap(tap); } switch (tap.getName()) { case INSTRUMENT_COMPLEX_INPUT: removeComplexListener((ComplexTap) tap); break; case INSTRUMENT_BASEBAND_FILTER_OUTPUT: mBasebandFilter.setListener(mAGC); break; case INSTRUMENT_AGC_OUTPUT: mAGC.setListener(mCQPSKDemodulator); break; case INSTRUMENT_QPSK_DEMODULATOR_OUTPUT: mCQPSKDemodulator.setListener(mCQPSKSlicer); break; case INSTRUMENT_CQPSK_SLICER_OUTPUT: mCQPSKSlicer.removeListener((DibitTap) tap); break; case INSTRUMENT_REAL_INPUT: FloatTap inputAGC = (FloatTap) tap; removeRealListener(inputAGC); addRealSampleListener(mDGC); break; case INSTRUMENT_DGC_OUTPUT: mDGC.setListener(mSymbolFilter); break; case INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT: mSymbolFilter.setListener(mC4FMSlicer); break; case INSTRUMENT_C4FM_SLICER_OUTPUT: DibitTap slicerTap = (DibitTap) tap; if (mC4FMSlicer != null) { mC4FMSlicer.removeListener(slicerTap); } break; } }
@Override public void addTap(Tap tap) { if (mSymbolFilter != null) { mSymbolFilter.addTap(tap); } if (mCQPSKDemodulator != null) { mCQPSKDemodulator.addTap(tap); } switch (tap.getName()) { case INSTRUMENT_COMPLEX_INPUT: addComplexListener((ComplexTap) tap); break; case INSTRUMENT_BASEBAND_FILTER_OUTPUT: ComplexTap baseband = (ComplexTap) tap; mBasebandFilter.setListener(baseband); baseband.setListener(mAGC); break; case INSTRUMENT_AGC_OUTPUT: ComplexTap agcSymbol = (ComplexTap) tap; mAGC.setListener(agcSymbol); agcSymbol.setListener(mCQPSKDemodulator); break; case INSTRUMENT_QPSK_DEMODULATOR_OUTPUT: QPSKTap qpsk = (QPSKTap) tap; mCQPSKDemodulator.setListener(qpsk); qpsk.setListener(mCQPSKSlicer); break; case INSTRUMENT_CQPSK_SLICER_OUTPUT: mCQPSKSlicer.addListener((DibitTap) tap); break; case INSTRUMENT_REAL_INPUT: FloatTap inputAGC = (FloatTap) tap; removeRealListener(mDGC); addRealSampleListener(inputAGC); inputAGC.setListener(mDGC); break; case INSTRUMENT_DGC_OUTPUT: FloatTap dgcSymbol = (FloatTap) tap; mDGC.setListener(dgcSymbol); dgcSymbol.setListener(mSymbolFilter); break; case INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT: FloatTap symbolSlicer = (FloatTap) tap; mSymbolFilter.setListener(symbolSlicer); symbolSlicer.setListener(mC4FMSlicer); break; case INSTRUMENT_C4FM_SLICER_OUTPUT: DibitTap slicer = (DibitTap) tap; if (mC4FMSlicer != null) { mC4FMSlicer.addListener(slicer); } if (mCQPSKSlicer != null) { mCQPSKSlicer.addListener(slicer); } break; } }
public P25Decoder( ResourceManager resourceManager, SampleType sampleType, Modulation modulation, AliasList aliasList) { super(sampleType); mModulation = modulation; mAliasList = aliasList; mMessageProcessor = new P25MessageProcessor(mAliasList); mMessageProcessor.addMessageListener(this); if (modulation == Modulation.CQPSK) { /* Provide message framer with reference to the demod so that it * can detect and issue corrections for costas phase lock errors */ mCQPSKDemodulator = new CQPSKDemodulator(); mMessageFramer = new P25MessageFramer(mAliasList, mCQPSKDemodulator); } else { mMessageFramer = new P25MessageFramer(mAliasList); } mMessageFramer.setListener(mMessageProcessor); /* Setup demodulation chains based on sample type (real or complex) and * modulation (C4FM or CQPSK) */ if (mSourceSampleType == SampleType.COMPLEX) { if (modulation == Modulation.CQPSK) { mBasebandFilter = new ComplexFIRFilter( FilterFactory.getLowPass(48000, 7250, 8000, 60, WindowType.HANNING, true), 1.0); this.addComplexListener(mBasebandFilter); // mEqualizer = new CMAEqualizer( 1.0f, 0.005f ); // mBasebandFilter.setListener( mEqualizer ); mAGC = new ComplexFeedForwardGainControl(32); // mEqualizer.setListener( mAGC ); mBasebandFilter.setListener(mAGC); mAGC.setListener(mCQPSKDemodulator); mCQPSKSlicer = new QPSKPolarSlicer(); mCQPSKDemodulator.setListener(mCQPSKSlicer); mCQPSKSlicer.addListener(mMessageFramer); } else /* C4FM */ { mBasebandFilter = new ComplexFIRFilter( FilterFactory.getLowPass(48000, 6750, 7500, 60, WindowType.HANNING, true), 1.0); this.addComplexListener(mBasebandFilter); mFMDemodulator = new FMDiscriminator(1.0f); mBasebandFilter.setListener(mFMDemodulator); /* Route output of the FM demod back to this channel so that we * can process the output as if it were coming from any other * real sample source */ mFMDemodulator.setListener(getRealReceiver()); } } /* Processing chain for real samples & demodulated complex samples */ if (modulation == Modulation.C4FM) { mAudioFilter = new FloatFIRFilter( FilterFactory.getLowPass(48000, 3000, 4000, 48, WindowType.HAMMING, true), 1.0); addRealSampleListener(mAudioFilter); mDGC = new DirectGainControl(15.0f, 0.1f, 35.0f, 0.3f); mAudioFilter.setListener(mDGC); mFrequencyCorrection = new FrequencyCorrectionControl(MAXIMUM_FREQUENCY_CORRECTION); mSymbolFilter = new C4FMSymbolFilter(mDGC, mFrequencyCorrection); mDGC.setListener(mSymbolFilter); mC4FMSlicer = new C4FMSlicer(); mSymbolFilter.setListener(mC4FMSlicer); mC4FMSlicer.addListener(mMessageFramer); } mAudioOutput = new P25AudioOutput(resourceManager); mMessageProcessor.addMessageListener(mAudioOutput); }