26 #include <QNetworkAccessManager> 27 #include <QNetworkReply> 56 m_deviceAPI(deviceAPI),
57 m_inputSampleRate(48000),
58 m_inputFrequencyOffset(0),
59 m_interpolatorDistance(0.0f),
60 m_interpolatorDistanceRemain(0.0f),
66 m_squelchDelayLine(24000),
72 m_signalFormat(signalFormatNone),
73 m_settingsMutex(QMutex::Recursive)
122 messageQueue->
push(cmd);
125 void DSDDemod::feed(
const SampleVector::const_iterator& begin,
const SampleVector::const_iterator& end,
bool firstOfBurst)
136 for (SampleVector::const_iterator it = begin; it != end; ++it)
138 Complex c(it->real(), it->imag());
148 Real magsq = re*re + im*im;
208 sampleDSD = demod * 32768.0f;
245 Sample s(sample, delayedSample);
307 if (nbAudioSamples > 0)
322 if (nbAudioSamples > 0)
367 qDebug() <<
"DSDDemod::handleMessage";
372 qDebug() <<
"DSDDemod::handleMessage: MsgChannelizerNotification: inputSampleRate: " << notif.
getSampleRate()
382 qDebug(
"DSDDemod::handleMessage: MsgConfigureChannelizer");
393 qDebug(
"DSDDemod::handleMessage: MsgConfigureDSDDemod: m_rfBandwidth");
410 qDebug() <<
"DSDDemod::handleMessage: DSPConfigureAudio:" 411 <<
" sampleRate: " << sampleRate;
435 int upsampling = sampleRate / 8000;
437 qDebug(
"DSDDemod::applyAudioSampleRate: audio rate: %d upsample by %d", sampleRate, upsampling);
439 if (sampleRate % 8000 != 0) {
440 qDebug(
"DSDDemod::applyAudioSampleRate: audio will sound best with sample rates that are integer multiples of 8 kS/s");
449 qDebug() <<
"DSDDemod::applyChannelSettings:" 450 <<
" inputSampleRate: " << inputSampleRate
451 <<
" inputFrequencyOffset: " << inputFrequencyOffset;
474 qDebug() <<
"DSDDemod::applySettings: " 479 <<
" m_volume: " << settings.
m_volume 495 <<
" force: " << force;
497 QList<QString> reverseAPIKeys;
500 reverseAPIKeys.append(
"inputFrequencyOffset");
503 reverseAPIKeys.append(
"demodGain");
506 reverseAPIKeys.append(
"audioMute");
509 reverseAPIKeys.append(
"syncOrConstellation");
512 reverseAPIKeys.append(
"slot1On");
515 reverseAPIKeys.append(
"slot2On");
518 reverseAPIKeys.append(
"demodGain");
521 reverseAPIKeys.append(
"traceLengthMutliplier");
526 reverseAPIKeys.append(
"rfBandwidth");
537 reverseAPIKeys.append(
"fmDeviation");
543 reverseAPIKeys.append(
"squelchGate");
550 reverseAPIKeys.append(
"squelch");
557 reverseAPIKeys.append(
"volume");
563 reverseAPIKeys.append(
"baudRate");
569 reverseAPIKeys.append(
"enableCosineFiltering");
575 reverseAPIKeys.append(
"tdmaStereo");
581 reverseAPIKeys.append(
"pllLock");
587 reverseAPIKeys.append(
"highPassFilter");
593 reverseAPIKeys.append(
"audioDeviceName");
651 case DSDcc::DSDDecoder::DSDSyncDMRDataMS:
652 case DSDcc::DSDDecoder::DSDSyncDMRDataP:
653 case DSDcc::DSDDecoder::DSDSyncDMRVoiceMS:
654 case DSDcc::DSDDecoder::DSDSyncDMRVoiceP:
657 strcpy(
m_formatStatusText,
"Sta: __ S1: __________________________ S2: __________________________");
662 case DSDcc::DSDDecoder::DSDBaseStation:
665 case DSDcc::DSDDecoder::DSDMobileStation:
677 case DSDcc::DSDDecoder::DSDSyncDStarHeaderN:
678 case DSDcc::DSDDecoder::DSDSyncDStarHeaderP:
679 case DSDcc::DSDDecoder::DSDSyncDStarN:
680 case DSDcc::DSDDecoder::DSDSyncDStarP:
685 strcpy(
m_formatStatusText,
"________/____>________|________>________|____________________|______:___/_____._");
695 if (rpt1.length() > 0) {
698 if (rpt2.length() > 0) {
701 if (yrSign.length() > 0) {
704 if (mySign.length() > 0) {
711 getDecoder().getDStarDecoder().getDistance());
717 case DSDcc::DSDDecoder::DSDSyncDPMR:
719 DSDcc::DSDdPMR::dpmrFrameTypes[(
int)
getDecoder().getDPMRDecoder().getFrameType()],
725 case DSDcc::DSDDecoder::DSDSyncNXDNP:
726 case DSDcc::DSDDecoder::DSDSyncNXDNN:
727 if (
getDecoder().getNXDNDecoder().getRFChannel() == DSDcc::DSDNXDN::NXDNRCCH)
733 getDecoder().getNXDNDecoder().isFullRate() ?
"F" :
"H",
735 getDecoder().getNXDNDecoder().getMessageType(),
736 getDecoder().getNXDNDecoder().getLocationId(),
737 getDecoder().getNXDNDecoder().getServicesFlag());
739 else if ((
getDecoder().getNXDNDecoder().getRFChannel() == DSDcc::DSDNXDN::NXDNRTCH)
740 || (
getDecoder().getNXDNDecoder().getRFChannel() == DSDcc::DSDNXDN::NXDNRDCH))
751 getDecoder().getNXDNDecoder().getRFChannelStr(),
752 getDecoder().getNXDNDecoder().isFullRate() ?
"F" :
"H",
754 getDecoder().getNXDNDecoder().getMessageType(),
756 getDecoder().getNXDNDecoder().isGroupCall() ?
'G' :
'I',
757 getDecoder().getNXDNDecoder().getDestinationId());
769 case DSDcc::DSDDecoder::DSDSyncYSF:
773 if (
getDecoder().getYSFDecoder().getFICHError() == DSDcc::DSDYSF::FICHNoError)
775 snprintf(
m_formatStatusText, 82,
"%s ", DSDcc::DSDYSF::ysfChannelTypeText[(
int)
getDecoder().getYSFDecoder().getFICH().getFrameInformation()]);
783 DSDcc::DSDYSF::ysfDataTypeText[(
int)
getDecoder().getYSFDecoder().getFICH().getDataType()],
784 DSDcc::DSDYSF::ysfCallModeText[(
int)
getDecoder().getYSFDecoder().getFICH().getCallMode()],
785 getDecoder().getYSFDecoder().getFICH().getBlockTotal(),
786 getDecoder().getYSFDecoder().getFICH().getFrameTotal(),
787 (
getDecoder().getYSFDecoder().getFICH().isNarrowMode() ?
'N' :
'W'),
788 (
getDecoder().getYSFDecoder().getFICH().isInternetPath() ?
'I' :
'L'));
790 if (
getDecoder().getYSFDecoder().getFICH().isSquelchCodeEnabled())
801 if (
getDecoder().getYSFDecoder().radioIdMode())
803 snprintf(dest, 12,
"%-5s:%-5s",
809 snprintf(dest, 11,
"%-10s",
getDecoder().getYSFDecoder().getDest());
832 QString& errorMessage)
843 const QStringList& channelSettingsKeys,
845 QString& errorMessage)
849 bool frequencyOffsetChanged =
false;
851 if (channelSettingsKeys.contains(
"inputFrequencyOffset"))
854 frequencyOffsetChanged =
true;
856 if (channelSettingsKeys.contains(
"rfBandwidth")) {
859 if (channelSettingsKeys.contains(
"fmDeviation")) {
862 if (channelSettingsKeys.contains(
"demodGain")) {
865 if (channelSettingsKeys.contains(
"volume")) {
868 if (channelSettingsKeys.contains(
"baudRate")) {
871 if (channelSettingsKeys.contains(
"squelchGate")) {
874 if (channelSettingsKeys.contains(
"squelch")) {
877 if (channelSettingsKeys.contains(
"audioMute")) {
880 if (channelSettingsKeys.contains(
"enableCosineFiltering")) {
883 if (channelSettingsKeys.contains(
"syncOrConstellation")) {
886 if (channelSettingsKeys.contains(
"slot1On")) {
889 if (channelSettingsKeys.contains(
"slot2On")) {
892 if (channelSettingsKeys.contains(
"tdmaStereo")) {
895 if (channelSettingsKeys.contains(
"pllLock")) {
898 if (channelSettingsKeys.contains(
"rgbColor")) {
901 if (channelSettingsKeys.contains(
"title")) {
904 if (channelSettingsKeys.contains(
"audioDeviceName")) {
907 if (channelSettingsKeys.contains(
"highPassFilter")) {
910 if (channelSettingsKeys.contains(
"traceLengthMutliplier")) {
913 if (channelSettingsKeys.contains(
"traceStroke")) {
916 if (channelSettingsKeys.contains(
"traceDecay")) {
919 if (channelSettingsKeys.contains(
"useReverseAPI")) {
922 if (channelSettingsKeys.contains(
"reverseAPIAddress")) {
925 if (channelSettingsKeys.contains(
"reverseAPIPort")) {
928 if (channelSettingsKeys.contains(
"reverseAPIDeviceIndex")) {
931 if (channelSettingsKeys.contains(
"reverseAPIChannelIndex")) {
935 if (frequencyOffsetChanged)
945 qDebug(
"DSDDemod::webapiSettingsPutPatch: forward to GUI: %p",
m_guiMessageQueue);
959 QString& errorMessage)
1019 double magsqAvg, magsqPeak;
1050 if (channelSettingsKeys.contains(
"inputFrequencyOffset") || force) {
1053 if (channelSettingsKeys.contains(
"rfBandwidth") || force) {
1056 if (channelSettingsKeys.contains(
"fmDeviation") || force) {
1059 if (channelSettingsKeys.contains(
"demodGain") || force) {
1062 if (channelSettingsKeys.contains(
"volume") || force) {
1065 if (channelSettingsKeys.contains(
"baudRate") || force) {
1068 if (channelSettingsKeys.contains(
"squelchGate") || force) {
1071 if (channelSettingsKeys.contains(
"squelch") || force) {
1074 if (channelSettingsKeys.contains(
"audioMute") || force) {
1077 if (channelSettingsKeys.contains(
"enableCosineFiltering") || force) {
1080 if (channelSettingsKeys.contains(
"syncOrConstellation") || force) {
1083 if (channelSettingsKeys.contains(
"slot1On") || force) {
1086 if (channelSettingsKeys.contains(
"slot2On") || force) {
1089 if (channelSettingsKeys.contains(
"tdmaStereo") || force) {
1092 if (channelSettingsKeys.contains(
"pllLock") || force) {
1095 if (channelSettingsKeys.contains(
"rgbColor") || force) {
1098 if (channelSettingsKeys.contains(
"title") || force) {
1101 if (channelSettingsKeys.contains(
"audioDeviceName") || force) {
1104 if (channelSettingsKeys.contains(
"highPassFilter") || force) {
1107 if (channelSettingsKeys.contains(
"traceLengthMutliplier") || force) {
1110 if (channelSettingsKeys.contains(
"traceStroke") || force) {
1113 if (channelSettingsKeys.contains(
"traceDecay") || force) {
1117 QString channelSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
1123 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
1125 QBuffer *buffer=
new QBuffer();
1126 buffer->open((QBuffer::ReadWrite));
1127 buffer->write(swgChannelSettings->
asJson().toUtf8());
1133 delete swgChannelSettings;
1138 QNetworkReply::NetworkError replyError = reply->error();
1142 qWarning() <<
"DSDDemod::networkManagerFinished:" 1143 <<
" error(" << (int) replyError
1144 <<
"): " << replyError
1145 <<
": " << reply->errorString();
1149 QString answer = reply->readAll();
1151 qDebug(
"DSDDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
void setVolume(float volume)
void setSquelch(float squelch)
void setPllLocked(qint32 pll_locked)
void setOriginatorChannelIndex(qint32 originator_channel_index)
void addAudioSink(AudioFifo *audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex=-1)
Add the audio sink.
PhaseDiscriminators m_phaseDiscri
QByteArray serialize() const
void setSquelchGate(qint32 squelch_gate)
void setSlot1On(qint32 slot1_on)
int getOutputSampleRate(int outputDeviceIndex=-1)
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
const DSDcc::DSDDstar & getDStarDecoder() const
Complex nextIQ()
Return next complex sample.
bool decimate(Real *distance, const Complex &next, Complex *result)
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
void setChannelSampleRate(qint32 channel_sample_rate)
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const DSDDemodSettings &settings)
void getMagSqLevels(double &avg, double &peak, int &nbSamples)
void push(Message *message, bool emitSignal=true)
Push message onto queue.
AudioVector m_audioBuffer
ThreadedBasebandSampleSink * m_threadedChannelizer
void setInLevel(qint32 in_level)
QString * getReverseApiAddress()
MovingAverageUtil< Real, double, 16 > m_movingAverage
void removeChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
char m_formatStatusText[82+1]
Fixed signal format dependent status text.
static double dbPower(double magsq, double floor=1e-12)
void addChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
QString m_audioDeviceName
void create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
static const QString m_channelIdURI
void setFMScaling(Real fmScaling)
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
void setBaudRate(qint32 baud_rate)
virtual bool deserialize(const QByteArray &data)
int m_traceLengthMutliplier
int getDeviceSetIndex() const
void setTraceStroke(qint32 trace_stroke)
int getOutputDeviceIndex(const QString &deviceName) const
QString * getAudioDeviceName()
void setUseReverseApi(qint32 use_reverse_api)
int getSampleRate() const
static const int m_udpBlockSize
void setDsdDemodReport(SWGDSDDemodReport *dsd_demod_report)
void removeAudioSink(AudioFifo *audioFifo)
Remove the audio sink.
void setBaudRate(int baudRate)
int m_inputFrequencyOffset
SampleVector m_scopeSampleBuffer
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void setSyncOrConstellation(qint32 sync_or_constellation)
void setStatusText(QString *status_text)
void setHighPassFilter(qint32 high_pass_filter)
void setSlot2On(qint32 slot2_on)
SWGDSDDemodReport * getDsdDemodReport()
void useHPMbelib(bool useHP)
qint32 getReverseApiChannelIndex()
void setChannelPowerDb(float channel_power_db)
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool po)
void setChannelType(QString *channel_type)
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool positiveOnly)=0
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
void applySettings(const DSDDemodSettings &settings, bool force=false)
qint64 m_inputFrequencyOffset
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
quint32 m_audioSampleRate
bool m_syncOrConstellation
void write(const T &element)
int getSamplesPerSymbol() const
void setTDMAStereo(bool tdmaStereo)
qint32 getUseReverseApi()
void enableMbelib(bool enable)
void setTitle(QString *title)
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const DSDDemodSettings &settings, bool force)
uint16_t m_reverseAPIDeviceIndex
void setAudioSampleRate(qint32 audio_sample_rate)
void setSquelch(qint32 squelch)
void setTdmaStereo(qint32 tdma_stereo)
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
void setUpsampling(int upsampling)
short getFilteredSample() const
SWGDSDDemodSettings * getDsdDemodSettings()
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
DownChannelizer * m_channelizer
void setRgbColor(qint32 rgb_color)
static DSPEngine * instance()
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
void setAudioDeviceName(QString *audio_device_name)
DoubleBufferFIFO< Real > m_squelchDelayLine
Interpolator m_interpolator
uint16_t m_reverseAPIPort
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
void pushMbeFrame(const unsigned char *mbeFrame, int mbeRateIndex, int mbeVolumeIndex, unsigned char channels, bool useHP, int upsampling, AudioFifo *audioFifo)
void setReverseApiAddress(QString *reverse_api_address)
BasebandSampleSink * m_scopeXY
int getMbeRateIndex() const
qint64 getInputFrequencyOffset()
bool deserialize(const QByteArray &data)
Real phaseDiscriminator(const Complex &sample)
static bool match(const Message *message)
DSDDemodSettings m_settings
void applyAudioSampleRate(int sampleRate)
short * getAudio2(int &nbSamples)
void setFreq(Real freq, Real sampleRate)
void setFmDeviation(float fm_deviation)
DSDDemod(DeviceAPI *deviceAPI)
void networkManagerFinished(QNetworkReply *reply)
void setTraceLengthMutliplier(qint32 trace_length_mutliplier)
qint32 getReverseApiDeviceIndex()
void removeChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Remove a channel sink (Rx)
void enableCosineFiltering(bool on)
void setTraceDecay(qint32 trace_decay)
void setZeroCrossingPosition(qint32 zero_crossing_position)
void setDirection(qint32 direction)
void setCarierPosition(qint32 carier_position)
FixReal * m_sampleBuffer
samples ring buffer
void configureMyPosition(MessageQueue *messageQueue, float myLatitude, float myLongitude)
SignalFormat m_signalFormat
Used to keep formatting during successive calls for the same standard type.
Real m_interpolatorDistance
void setRfBandwidth(float rf_bandwidth)
virtual QString asJson() override
short getSymbolSyncSample() const
Real m_interpolatorDistanceRemain
qint32 getSyncOrConstellation()
void setSlot1On(qint32 slot1_on)
void setSlot2On(qint32 slot2_on)
AudioDeviceManager * getAudioDeviceManager()
qint32 getHighPassFilter()
void addChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Add a channel sink (Rx)
static const QString m_channelId
const char * updateAndGetStatusText()
void setAudioGain(float gain)
qint32 getReverseApiPort()
virtual QByteArray serialize() const
QNetworkAccessManager * m_networkManager
void setDsdDemodSettings(SWGDSDDemodSettings *dsd_demod_settings)
void setDemodGain(float demod_gain)
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
void setMyPoint(float lat, float lon)
uint16_t m_reverseAPIChannelIndex
void setAudioMute(qint32 audio_mute)
qint32 getEnableCosineFiltering()
const unsigned char * getMbeDVFrame1() const
void pushSample(short sample)
void setSymbolPLLLock(bool pllLock)
short * getAudio1(int &nbSamples)
qint32 getTraceLengthMutliplier()
int getIndexInDeviceSet() const
void setSyncType(QString *sync_type)
std::complex< Real > Complex
const unsigned char * getMbeDVFrame2() const
const DSDDecoder & getDecoder() const
qint64 getFrequencyOffset() const
QString m_reverseAPIAddress
bool m_enableCosineFiltering
void setEnableCosineFiltering(qint32 enable_cosine_filtering)
uint32_t write(const quint8 *data, uint32_t numSamples)
QNetworkRequest m_networkRequest
void setReverseApiPort(qint32 reverse_api_port)
void setSyncRate(qint32 sync_rate)
void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force=false)
void setPllLock(qint32 pll_lock)
void setInputFrequencyOffset(qint64 input_frequency_offset)