M17: reworked ClockRecovery

pull/1370/head
f4exb 2022-07-27 14:58:33 +02:00
rodzic 414e695121
commit 1601fa43ca
4 zmienionych plików z 38 dodań i 21 usunięć

Wyświetl plik

@ -1,6 +1,7 @@
project(modemm17) project(modemm17)
set(modemm17_SOURCES set(modemm17_SOURCES
ClockRecovery.cpp
Correlator.cpp Correlator.cpp
FreqDevEstimator.cpp FreqDevEstimator.cpp
Golay24.cpp Golay24.cpp

Wyświetl plik

@ -0,0 +1,7 @@
#include "ClockRecovery.h"
namespace modemm17
{
const float ClockRecovery::MAX_CLOCK = 1.0005;
const float ClockRecovery::MIN_CLOCK = 0.9995;
}

Wyświetl plik

@ -2,7 +2,7 @@
#pragma once #pragma once
#include <array> #include <vector>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <numeric> #include <numeric>
@ -37,16 +37,9 @@ namespace modemm17
* @inv sample_index_ is in the interval [0, SAMPLES_PER_SYMBOL). * @inv sample_index_ is in the interval [0, SAMPLES_PER_SYMBOL).
* @inv clock_ is in the interval [0.9995, 1.0005] * @inv clock_ is in the interval [0.9995, 1.0005]
*/ */
template <size_t SampleRate, size_t SymbolRate>
class ClockRecovery class ClockRecovery
{ {
static constexpr size_t SAMPLES_PER_SYMBOL = SampleRate / SymbolRate; std::vector<float> estimates_;
static constexpr int8_t MAX_OFFSET = SAMPLES_PER_SYMBOL / 2;
static constexpr float dx = 1.0 / SAMPLES_PER_SYMBOL;
static constexpr float MAX_CLOCK = 1.0005;
static constexpr float MIN_CLOCK = 0.9995;
std::array<float, SAMPLES_PER_SYMBOL> estimates_;
size_t sample_count_ = 0; size_t sample_count_ = 0;
uint16_t frame_count_ = 0; uint16_t frame_count_ = 0;
uint8_t sample_index_ = 0; uint8_t sample_index_ = 0;
@ -76,7 +69,7 @@ class ClockRecovery
// Find falling edge. // Find falling edge.
bool is_positive = false; bool is_positive = false;
for (size_t i = 0; i != SAMPLES_PER_SYMBOL; ++i) for (size_t i = 0; i != samples_per_symbol_; ++i)
{ {
float phase = estimates_[i]; float phase = estimates_[i];
@ -91,7 +84,7 @@ class ClockRecovery
} }
} }
sample_index_ = index == 0 ? SAMPLES_PER_SYMBOL - 1 : index - 1; sample_index_ = index == 0 ? samples_per_symbol_ - 1 : index - 1;
} }
/** /**
@ -104,13 +97,13 @@ class ClockRecovery
int8_t offset = sample_index_ - prev_sample_index_; int8_t offset = sample_index_ - prev_sample_index_;
// When in spec, the clock should drift by less than 1 sample per frame. // When in spec, the clock should drift by less than 1 sample per frame.
if (offset >= MAX_OFFSET) if (offset >= max_offset_)
{ {
offset -= SAMPLES_PER_SYMBOL; offset -= samples_per_symbol_;
} }
else if (offset <= -MAX_OFFSET) else if (offset <= -max_offset_)
{ {
offset += SAMPLES_PER_SYMBOL; offset += samples_per_symbol_;
} }
return offset; return offset;
@ -135,9 +128,15 @@ class ClockRecovery
} }
public: public:
ClockRecovery() ClockRecovery(size_t sampleRate, size_t symbolRate) :
sampleRate_(sampleRate),
symbolRate_(symbolRate)
{ {
estimates_.fill(0); samples_per_symbol_ = sampleRate_ / symbolRate_;
max_offset_ = samples_per_symbol_ / 2;
dx_ = 1.0 / samples_per_symbol_;
estimates_.resize(samples_per_symbol_);
std::fill(estimates_.begin(), estimates_.end(), 0);
} }
/** /**
@ -158,7 +157,7 @@ public:
estimates_[index_] += dy; estimates_[index_] += dy;
index_ += 1; index_ += 1;
if (index_ == SAMPLES_PER_SYMBOL) if (index_ == samples_per_symbol_)
{ {
index_ = 0; index_ = 0;
} }
@ -175,7 +174,7 @@ public:
frame_count_ = 0; frame_count_ = 0;
index_ = 0; index_ = 0;
sample_index_ = 0; sample_index_ = 0;
estimates_.fill(0); std::fill(estimates_.begin(), estimates_.end(), 0);
} }
/** /**
@ -234,9 +233,18 @@ public:
frame_count_ = std::min(0x1000, 1 + frame_count_); frame_count_ = std::min(0x1000, 1 + frame_count_);
sample_count_ = 0; sample_count_ = 0;
estimates_.fill(0); std::fill(estimates_.begin(), estimates_.end(), 0);
return true; return true;
} }
private:
size_t sampleRate_;
size_t symbolRate_;
size_t samples_per_symbol_;
int8_t max_offset_;
float dx_;
static const float MAX_CLOCK;
static const float MIN_CLOCK;
}; };
} // modemm17 } // modemm17

Wyświetl plik

@ -48,7 +48,7 @@ struct MODEMM17_API M17Demodulator
}; };
DataCarrierDetect<SAMPLE_RATE, 500> dcd{2500, 4000, 1.0, 4.0}; DataCarrierDetect<SAMPLE_RATE, 500> dcd{2500, 4000, 1.0, 4.0};
ClockRecovery<SAMPLE_RATE, SYMBOL_RATE> clock_recovery; ClockRecovery clock_recovery;
sync_word_t preamble_sync{{+3, -3, +3, -3, +3, -3, +3, -3}, 29.f}; sync_word_t preamble_sync{{+3, -3, +3, -3, +3, -3, +3, -3}, 29.f};
sync_word_t lsf_sync{ {+3, +3, +3, +3, -3, -3, +3, -3}, 32.f, -31.f}; // LSF or STREAM (inverted) sync_word_t lsf_sync{ {+3, +3, +3, +3, -3, -3, +3, -3}, 32.f, -31.f}; // LSF or STREAM (inverted)
@ -77,6 +77,7 @@ struct MODEMM17_API M17Demodulator
diagnostic_callback_t diagnostic_callback; diagnostic_callback_t diagnostic_callback;
M17Demodulator(callback_t callback) : M17Demodulator(callback_t callback) :
clock_recovery(SAMPLE_RATE, SYMBOL_RATE),
decoder(callback), decoder(callback),
initializing_count_(1920) initializing_count_(1920)
{ {