From c3f55af6a660b7bd9d01d40b58780959637bd7fb Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 6 Jul 2022 07:01:42 +0200 Subject: [PATCH] M17 demod: fixed BERT --- modems/CMakeLists.txt | 4 ++- modems/m17/M17Demodulator.cpp | 28 +++++++++++++------ modems/m17/M17Demodulator.h | 2 +- modems/m17/M17FrameDecoder.h | 21 ++++++++------ modems/m17/M17Modulator.h | 23 +++++++++------ modems/m17/Trellis.h | 2 +- plugins/channelrx/demodm17/m17demod.h | 15 +++++++++- plugins/channelrx/demodm17/m17demodbaseband.h | 15 +++++++++- plugins/channelrx/demodm17/m17demodgui.cpp | 21 +++++++++++--- plugins/channelrx/demodm17/m17demodgui.h | 2 +- plugins/channelrx/demodm17/m17demodgui.ui | 4 +-- .../channelrx/demodm17/m17demodprocessor.cpp | 2 ++ .../channelrx/demodm17/m17demodprocessor.h | 16 +++++++---- plugins/channelrx/demodm17/m17demodsink.h | 15 +++++++++- 14 files changed, 125 insertions(+), 45 deletions(-) diff --git a/modems/CMakeLists.txt b/modems/CMakeLists.txt index d0f954180..d8babc1d2 100644 --- a/modems/CMakeLists.txt +++ b/modems/CMakeLists.txt @@ -49,6 +49,8 @@ add_library(modems SHARED ${modems_SOURCES} ) -target_link_libraries(modems) +target_link_libraries(modems + Qt5::Core +) install(TARGETS modems DESTINATION ${INSTALL_LIB_DIR}) diff --git a/modems/m17/M17Demodulator.cpp b/modems/m17/M17Demodulator.cpp index 2b1eab658..8c2a55d44 100644 --- a/modems/m17/M17Demodulator.cpp +++ b/modems/m17/M17Demodulator.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "M17Demodulator.h" namespace modemm17 { @@ -103,6 +106,7 @@ void M17Demodulator::dcd_off() dev.deviation(), dev.offset(), (int) demodState, + (int) sync_word_type, clock_recovery.clock_estimate(), sample_index, sync_sample_index, @@ -210,7 +214,7 @@ void M17Demodulator::do_lsf_sync() if (sync_triggered > 0.1) { - std::cerr << "M17Demodulator::do_lsf_sync: preamble:" << sync_triggered << std::endl; + qDebug() << "modemm17::M17Demodulator::do_lsf_sync: preamble:" << sync_triggered; return; } @@ -218,11 +222,11 @@ void M17Demodulator::do_lsf_sync() bert_triggered = packet_sync.triggered(correlator); if (sync_triggered != 0) { - std::cerr << "M17Demodulator::do_lsf_sync: sync_triggered:" << sync_triggered << std::endl; + qDebug() << "modemm17::M17Demodulator::do_lsf_sync: sync_triggered:" << sync_triggered; } if (bert_triggered != 0) { - std::cerr << "M17Demodulator::do_lsf_sync: bert_triggered:" << bert_triggered << std::endl; + qDebug() << "modemm17::M17Demodulator::do_lsf_sync: bert_triggered:" << bert_triggered; } if (bert_triggered < 0) @@ -232,7 +236,7 @@ void M17Demodulator::do_lsf_sync() update_values(sample_index); demodState = DemodState::FRAME; sync_word_type = M17FrameDecoder::SyncWordType::BERT; - std::cerr << "M17Demodulator::do_lsf_sync: BERT:" << (int) sync_word_type << std::endl; + qDebug() << "modemm17::M17Demodulator::do_lsf_sync: BERT:" << (int) sync_word_type; } else if (bert_triggered > 0) { @@ -241,7 +245,7 @@ void M17Demodulator::do_lsf_sync() update_values(sample_index); demodState = DemodState::FRAME; sync_word_type = M17FrameDecoder::SyncWordType::PACKET; - std::cerr << "M17Demodulator::do_lsf_sync: PACKET:" << (int) sync_word_type << std::endl; + qDebug() << "modemm17::M17Demodulator::do_lsf_sync: PACKET:" << (int) sync_word_type; } else if (std::abs(sync_triggered) > 0.1) { @@ -253,13 +257,13 @@ void M17Demodulator::do_lsf_sync() { demodState = DemodState::FRAME; sync_word_type = M17FrameDecoder::SyncWordType::LSF; - std::cerr << "M17Demodulator::do_lsf_sync: LSF:" << (int) sync_word_type << std::endl; + qDebug() << "modemm17::M17Demodulator::do_lsf_sync: LSF:" << (int) sync_word_type; } else { demodState = DemodState::FRAME; sync_word_type = M17FrameDecoder::SyncWordType::STREAM; - std::cerr << "M17Demodulator::do_lsf_sync: STREAM:" << (int) sync_word_type << std::endl; + qDebug() << "modemm17::M17Demodulator::do_lsf_sync: STREAM:" << (int) sync_word_type; } } else if (++missing_sync_count > 192) @@ -267,7 +271,7 @@ void M17Demodulator::do_lsf_sync() demodState = DemodState::UNLOCKED; decoder.reset(); missing_sync_count = 0; - std::cerr << "M17Demodulator::do_lsf_sync: UNLOCKED:" << (int) sync_word_type << std::endl; + qDebug() << "modemm17::M17Demodulator::do_lsf_sync: UNLOCKED:" << (int) sync_word_type; } else { @@ -403,7 +407,6 @@ void M17Demodulator::do_frame(float filtered_sample) if (len != 0) { - // std::cerr << "M17Demodulator::do_frame: sync_word_type:" << (int) sync_word_type << " len:" << len << std::endl; need_clock_update_ = true; M17FrameDecoder::input_buffer_t buffer; std::copy(tmp, tmp + len, buffer.begin()); @@ -411,6 +414,11 @@ void M17Demodulator::do_frame(float filtered_sample) cost_count = viterbi_cost > 90 ? cost_count + 1 : 0; cost_count = viterbi_cost > 100 ? cost_count + 1 : cost_count; cost_count = viterbi_cost > 110 ? cost_count + 1 : cost_count; + // qDebug() << "modemm17::M17Demodulator::do_frame: " + // << "sync_word_type:" << (int) sync_word_type + // << " len:" << len + // << " viterbi_cost: " << viterbi_cost + // << " cost_count" << cost_count; if (cost_count > 75) { @@ -487,6 +495,7 @@ void M17Demodulator::operator()(const float input) dev.deviation(), dev.offset(), (int) demodState, + (int) sync_word_type, clock_recovery.clock_estimate(), sample_index, sync_sample_index, @@ -575,6 +584,7 @@ void M17Demodulator::operator()(const float input) dev.deviation(), dev.offset(), (int) demodState, + (int) sync_word_type, clock_recovery.clock_estimate(), sample_index, sync_sample_index, diff --git a/modems/m17/M17Demodulator.h b/modems/m17/M17Demodulator.h index 6b9c11b6a..1603ed274 100644 --- a/modems/m17/M17Demodulator.h +++ b/modems/m17/M17Demodulator.h @@ -37,7 +37,7 @@ struct M17_API M17Demodulator using collelator_t = Correlator; using sync_word_t = SyncWord; using callback_t = M17FrameDecoder::callback_t; - using diagnostic_callback_t = std::function; + using diagnostic_callback_t = std::function; enum class DemodState { UNLOCKED, diff --git a/modems/m17/M17FrameDecoder.h b/modems/m17/M17FrameDecoder.h index 987e5e63b..5464d302b 100644 --- a/modems/m17/M17FrameDecoder.h +++ b/modems/m17/M17FrameDecoder.h @@ -2,6 +2,9 @@ #pragma once +#include +#include + #include "M17Randomizer.h" #include "PolynomialInterleaver.h" #include "Trellis.h" @@ -22,15 +25,16 @@ namespace modemm17 template -void dump(const std::array& data, char header = 'D') +QString dump(const std::array& data, char header = 'D') { - std::cerr << header << " = "; + QString s(header); + s += "="; for (auto c : data) { - std::cerr << std::hex << std::setw(2) << std::setfill('0') << (int) c << " "; + s += QString("%1 ").arg((int) c, 2, 16, QChar('0')); } - std::cerr << std::dec << std::endl; + return s; } struct M17FrameDecoder @@ -153,8 +157,7 @@ struct M17FrameDecoder viterbi_cost = viterbi_.decode(depuncture_buffer.lsf, decode_buffer.lsf); to_byte_array(decode_buffer.lsf, output_buffer.lsf); - // std::cerr << "M17FrameDecoder::decode_lsf: vierbi:" << viterbi_cost << std::endl; - // dump(output_buffer.lsf); + // qDebug() << "modemm17::M17FrameDecoder::decode_lsf: vierbi:" << viterbi_cost < +#include + #include "FirFilter.h" #include "LinkSetupFrame.h" #include "CRC16.h" @@ -177,7 +180,7 @@ public: auto size = puncture(encoded, punctured, P1); if (size != 368) { - std::cerr << "modemm17::M17Modulator::make_lsf: incorrect size (not 368)" << size; + qWarning() << "modemm17::M17Modulator::make_lsf: incorrect size (not 368)" << size; } interleaver.interleave(punctured); @@ -277,7 +280,7 @@ public: auto size = modemm17::puncture(encoded, punctured, modemm17::P2); if (size != 272) { - std::cerr << "modemm17::M17Modulator::make_stream_data_frame: incorrect size (not 272)" << size; + qWarning() << "modemm17::M17Modulator::make_stream_data_frame: incorrect size (not 272)" << size; } return punctured; @@ -310,7 +313,9 @@ public: packet_assembly[25] = 0x80 | ((packet_size+2)<<2); // sent packet size includes CRC packet_assembly[packet_size] = crc_.get_bytes()[1]; packet_assembly[packet_size+1] = crc_.get_bytes()[0]; - std::cerr << "M17Modulator::make_packet_frame:" << std::hex << (int) crc_.get_bytes()[1] << ":" << (int) crc_.get_bytes()[0] << std::endl; + qDebug() << QString("modemm17::M17Modulator::make_packet_frame: %1:%2") + .arg((int) crc_.get_bytes()[1], 2, 16, QChar('0')) + .arg((int) crc_.get_bytes()[0], 2, 16, QChar('0')); } else { @@ -359,7 +364,7 @@ public: auto size = puncture(encoded, punctured, P3); if (size != 368) { - std::cerr << "modemm17::M17Modulator::make_packet_frame: incorrect size (not 368)" << size; + qWarning() << "modemm17::M17Modulator::make_packet_frame: incorrect size (not 368)" << size; } interleaver.interleave(punctured); @@ -372,7 +377,7 @@ public: { std::array data; // 24.6125 bytes, 197 bits - // Generate the data. + // Generate the data (24*8 = 192 bits). for (size_t i = 0; i != data.size() - 1; ++i) { uint8_t byte = 0; @@ -386,8 +391,8 @@ public: data[i] = byte; } + // Generate the data (last 5 bits). uint8_t byte = 0; - for (int i = 0; i != 5; ++i) { byte <<= 1; @@ -397,10 +402,12 @@ public: byte <<= 3; data[24] = byte; + // Convolutional encode std::array encoded; size_t index = 0; uint32_t memory = 0; + // 24*8 = 192 first bits for (size_t i = 0; i != data.size() - 1; ++i) { auto b = data[i]; @@ -415,8 +422,8 @@ public: } } + // last 5 bits auto b = data[24]; - for (size_t j = 0; j != 5; ++j) { uint32_t x = (b & 0x80) >> 7; @@ -438,7 +445,7 @@ public: auto size = puncture(encoded, punctured, P2); if (size != 368) { - std::cerr << "modemm17::M17Modulator::make_bert_frame: incorrect size (not 368)" << size; + qWarning() << "modemm17::M17Modulator::make_bert_frame: incorrect size (not 368)" << size; } return punctured; diff --git a/modems/m17/Trellis.h b/modems/m17/Trellis.h index cfe0cd801..892df360e 100644 --- a/modems/m17/Trellis.h +++ b/modems/m17/Trellis.h @@ -47,7 +47,7 @@ constexpr auto P1 = std::array{ 1, 0, 1, 1 // M15 }; -/// Puncture matrix for audio frames. Rate 6/11. +/// Puncture matrix for audio and BERT frames. Rate 11/12. constexpr auto P2 = std::array{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}; diff --git a/plugins/channelrx/demodm17/m17demod.h b/plugins/channelrx/demodm17/m17demod.h index be2ebd26b..6d10c8277 100644 --- a/plugins/channelrx/demodm17/m17demod.h +++ b/plugins/channelrx/demodm17/m17demod.h @@ -219,6 +219,7 @@ public: float& deviation, float& offset, int& status, + int& sync_word_type, float& clock, int& sampleIndex, int& syncIndex, @@ -226,7 +227,19 @@ public: int& viterbiCost ) const { - m_basebandSink->getDiagnostics(dcd, evm, deviation, offset, status, clock, sampleIndex, syncIndex, clockIndex, viterbiCost); + m_basebandSink->getDiagnostics( + dcd, + evm, + deviation, + offset, + status, + sync_word_type, + clock, + sampleIndex, + syncIndex, + clockIndex, + viterbiCost + ); } uint32_t getLSFCount() const { return m_basebandSink->getLSFCount(); } diff --git a/plugins/channelrx/demodm17/m17demodbaseband.h b/plugins/channelrx/demodm17/m17demodbaseband.h index bac5205a3..446b61165 100644 --- a/plugins/channelrx/demodm17/m17demodbaseband.h +++ b/plugins/channelrx/demodm17/m17demodbaseband.h @@ -80,6 +80,7 @@ public: float& deviation, float& offset, int& status, + int& sync_word_type, float& clock, int& sampleIndex, int& syncIndex, @@ -87,7 +88,19 @@ public: int& viterbiCost ) const { - m_sink.getDiagnostics(dcd, evm, deviation, offset, status, clock, sampleIndex, syncIndex, clockIndex, viterbiCost); + m_sink.getDiagnostics( + dcd, + evm, + deviation, + offset, + status, + sync_word_type, + clock, + sampleIndex, + syncIndex, + clockIndex, + viterbiCost + ); } uint32_t getLSFCount() const { return m_sink.getLSFCount(); } diff --git a/plugins/channelrx/demodm17/m17demodgui.cpp b/plugins/channelrx/demodm17/m17demodgui.cpp index 807674aa8..137ddd621 100644 --- a/plugins/channelrx/demodm17/m17demodgui.cpp +++ b/plugins/channelrx/demodm17/m17demodgui.cpp @@ -604,13 +604,26 @@ void M17DemodGUI::tick() float deviation; float offset; int status; + int sync_word_type; float clock; int sampleIndex; int syncIndex; int clockIndex; int viterbiCost; - m_m17Demod->getDiagnostics(dcd, evm, deviation, offset, status, clock, sampleIndex, syncIndex, clockIndex, viterbiCost); + m_m17Demod->getDiagnostics( + dcd, + evm, + deviation, + offset, + status, + sync_word_type, + clock, + sampleIndex, + syncIndex, + clockIndex, + viterbiCost + ); if (dcd) { ui->dcdLabel->setStyleSheet("QLabel { background-color : green; }"); @@ -624,7 +637,7 @@ void M17DemodGUI::tick() ui->lockLabel->setStyleSheet("QLabel { background-color : green; }"); } - ui->syncText->setText(getStatus(status, m_m17Demod->getStreamElsePacket(), m_m17Demod->getStdPacketProtocol())); + ui->syncText->setText(getStatus(status, sync_word_type, m_m17Demod->getStreamElsePacket(), m_m17Demod->getStdPacketProtocol())); ui->evmText->setText(tr("%1").arg(evm*100.0f, 3, 'f', 1)); ui->deviationText->setText(tr("%1").arg(deviation/1.5f, 3, 'f', 2)); ui->offsetText->setText(tr("%1").arg(offset/1.5f, 3, 'f', 2)); @@ -657,11 +670,11 @@ void M17DemodGUI::tick() m_tickCount++; } -QString M17DemodGUI::getStatus(int status, bool streamElsePacket, int packetProtocol) +QString M17DemodGUI::getStatus(int status, int sync_word_type, bool streamElsePacket, int packetProtocol) { if (status == 0) { return "Unlocked"; - } else if (status == 4) { + } else if ((status == 5) && (sync_word_type == 3)) { return "BERT"; } else if (streamElsePacket) { return "Stream"; diff --git a/plugins/channelrx/demodm17/m17demodgui.h b/plugins/channelrx/demodm17/m17demodgui.h index dcf7242d8..9b0513441 100644 --- a/plugins/channelrx/demodm17/m17demodgui.h +++ b/plugins/channelrx/demodm17/m17demodgui.h @@ -110,7 +110,7 @@ private: bool handleMessage(const Message& message); void makeUIConnections(); void updateAbsoluteCenterFrequency(); - QString getStatus(int status, bool streamElsePacket, int packetProtocol); + QString getStatus(int status, int sync_word_type, bool streamElsePacket, int packetProtocol); void packetReceived(QByteArray packet); void leaveEvent(QEvent*); diff --git a/plugins/channelrx/demodm17/m17demodgui.ui b/plugins/channelrx/demodm17/m17demodgui.ui index a2ddb2ec2..2b1248a0f 100644 --- a/plugins/channelrx/demodm17/m17demodgui.ui +++ b/plugins/channelrx/demodm17/m17demodgui.ui @@ -1370,13 +1370,13 @@ 203 65 - 25 + 30 28 - 25 + 30 0 diff --git a/plugins/channelrx/demodm17/m17demodprocessor.cpp b/plugins/channelrx/demodm17/m17demodprocessor.cpp index 2711c59ac..cb46e7463 100644 --- a/plugins/channelrx/demodm17/m17demodprocessor.cpp +++ b/plugins/channelrx/demodm17/m17demodprocessor.cpp @@ -102,6 +102,7 @@ void M17DemodProcessor::diagnostic_callback( float deviation, float offset, int status, + int sync_word_type, float clock, int sample_index, int sync_index, @@ -116,6 +117,7 @@ void M17DemodProcessor::diagnostic_callback( m_this->m_deviation = deviation; m_this->m_offset = offset; m_this->m_status = status; + m_this->m_syncWordType = sync_word_type; m_this->m_clock = clock; m_this->m_sampleIndex = sample_index; m_this->m_syncIndex = sync_index; diff --git a/plugins/channelrx/demodm17/m17demodprocessor.h b/plugins/channelrx/demodm17/m17demodprocessor.h index 834e3d66c..f9f5d8428 100644 --- a/plugins/channelrx/demodm17/m17demodprocessor.h +++ b/plugins/channelrx/demodm17/m17demodprocessor.h @@ -71,6 +71,7 @@ public: float& deviation, float& offset, int& status, + int& sync_word_type, float& clock, int& sampleIndex, int& syncIndex, @@ -83,6 +84,7 @@ public: deviation = m_deviation; offset = m_offset; status = m_status; + sync_word_type = m_syncWordType; clock = m_clock; sampleIndex = m_sampleIndex; syncIndex = m_syncIndex; @@ -112,16 +114,17 @@ private: M17DemodAudioInterpolatorFilter m_upsamplingFilter; // Diagnostics - bool m_dcd; //!< Data Carrier Detect - float m_evm; //!< Error Vector Magnitude in percent - float m_deviation; //!< Estimated deviation. Ideal = 1.0 - float m_offset; //!< Estimated frequency offset. Ideal = 0.0 practically limited to ~[-0.18, 0.18] - int m_status; //!< Status + bool m_dcd; //!< Data Carrier Detect + float m_evm; //!< Error Vector Magnitude in percent + float m_deviation; //!< Estimated deviation. Ideal = 1.0 + float m_offset; //!< Estimated frequency offset. Ideal = 0.0 practically limited to ~[-0.18, 0.18] + int m_status; //!< Status + int m_syncWordType; //!< Sync word type float m_clock; int m_sampleIndex; int m_syncIndex; int m_clockIndex; - int m_viterbiCost; //!< [-1:128] ideally 0 + int m_viterbiCost; //!< [-1:128] ideally 0 QString m_srcCall; QString m_destCall; @@ -141,6 +144,7 @@ private: float deviation, float offset, int status, + int sync_word_type, float clock, int sample_index, int sync_index, diff --git a/plugins/channelrx/demodm17/m17demodsink.h b/plugins/channelrx/demodm17/m17demodsink.h index 97f163887..aae877525 100644 --- a/plugins/channelrx/demodm17/m17demodsink.h +++ b/plugins/channelrx/demodm17/m17demodsink.h @@ -82,6 +82,7 @@ public: float& deviation, float& offset, int& status, + int& sync_word_type, float& clock, int& sampleIndex, int& syncIndex, @@ -89,7 +90,19 @@ public: int& viterbiCost ) const { - m_m17DemodProcessor.getDiagnostics(dcd, evm, deviation, offset, status, clock, sampleIndex, syncIndex, clockIndex, viterbiCost); + m_m17DemodProcessor.getDiagnostics( + dcd, + evm, + deviation, + offset, + status, + sync_word_type, + clock, + sampleIndex, + syncIndex, + clockIndex, + viterbiCost + ); } uint32_t getLSFCount() const { return m_m17DemodProcessor.getLSFCount(); }