diff --git a/decoder_modules/m17_decoder/src/m17dsp.h b/decoder_modules/m17_decoder/src/m17dsp.h index 96398b12..d1513cd4 100644 --- a/decoder_modules/m17_decoder/src/m17dsp.h +++ b/decoder_modules/m17_decoder/src/m17dsp.h @@ -27,6 +27,10 @@ extern "C" { #define M17_RAW_FRAME_SIZE 384 #define M17_CUT_FRAME_SIZE 368 +#define M17_MAX_FN 0x7FFF +#define M17_END_FN 0x8000 +#define M17_STREAM_TIMEOUT 500 + const uint8_t M17_LSF_SYNC[16] = { 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1 }; const uint8_t M17_STF_SYNC[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1 }; const uint8_t M17_PKF_SYNC[16] = { 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; @@ -438,6 +442,7 @@ namespace dsp { void init(stream* in) { _in = in; + lastConseqTime = std::chrono::high_resolution_clock::now(); codec = codec2_create(CODEC2_MODE_3200); sampsPerC2Frame = codec2_samples_per_frame(codec); @@ -460,10 +465,46 @@ namespace dsp { block::tempStart(); } + bool isReceiving() { + std::lock_guard lck(recvMtx); + return receiving && !timedOut(); + } + + bool timedOut() { + std::lock_guard lck(recvMtx); + auto now = std::chrono::high_resolution_clock::now(); + return std::chrono::duration_cast(now - lastConseqTime).count() > M17_STREAM_TIMEOUT; + } + int run() { int count = _in->read(); if (count < 0) { return -1; } + // Decode frame number + uint16_t fn = ((uint16_t)_in->readBuf[0] << 8) | _in->readBuf[1]; + + // Check if we need to start or stop receiving + bool consecutive = ((((int)fn - (int)lastFn + M17_END_FN) % M17_END_FN) == 1); + if (!receiving && consecutive) { + std::lock_guard lck(recvMtx); + receiving = true; + } + else if (receiving && consecutive) { + std::lock_guard lck(recvMtx); + lastConseqTime = std::chrono::high_resolution_clock::now();; + } + else if (receiving && !consecutive && timedOut()) { + std::lock_guard lck(recvMtx); + receiving = false; + } + + // Save FN and if we have to stop receiving and it's not the last frame, stop + lastFn = fn; + if (!receiving) { + _in->flush(); + return count; + } + // Decode both parts using codec codec2_decode(codec, int16Audio, &_in->readBuf[2]); codec2_decode(codec, &int16Audio[sampsPerC2Frame], &_in->readBuf[2 + 8]); @@ -485,6 +526,11 @@ namespace dsp { private: stream* _in; + std::recursive_mutex recvMtx; + bool receiving = false; + uint16_t lastFn = 0; + std::chrono::high_resolution_clock::time_point lastConseqTime; + int16_t* int16Audio; float* floatAudio; @@ -637,6 +683,10 @@ namespace dsp { demod.setInput(input); } + bool isReceiving() { + return decodeAudio.isReceiving(); + } + stream* diagOut = NULL; stream* out = NULL; diff --git a/decoder_modules/m17_decoder/src/main.cpp b/decoder_modules/m17_decoder/src/main.cpp index 38224451..5c9d5372 100644 --- a/decoder_modules/m17_decoder/src/main.cpp +++ b/decoder_modules/m17_decoder/src/main.cpp @@ -227,6 +227,15 @@ private: config.release(true); } + ImGui::TextUnformatted("Status:"); + ImGui::SameLine(); + if (_this->decoder.isReceiving()) { + ImGui::TextColored(ImVec4(0.0, 1.0, 0.0, 1.0), "Receiving"); + } + else { + ImGui::TextUnformatted("Idle"); + } + if (!_this->enabled) { style::endDisabled(); } }