diff --git a/src/block_sync.cc b/src/block_sync.cc index cff6ba7..736d15a 100644 --- a/src/block_sync.cc +++ b/src/block_sync.cc @@ -208,6 +208,8 @@ void BlockStream::acquireSync(Block block) { if (is_in_sync_) return; + num_bits_since_sync_lost_++; + // Try to find a repeating offset sequence if (block.offset != Offset::invalid) { sync_buffer.push(block.offset, bitcount_); @@ -216,9 +218,7 @@ void BlockStream::acquireSync(Block block) { is_in_sync_ = true; expected_offset_ = block.offset; current_group_ = Group(); - } else { - previous_syncing_bitcount_= bitcount_; - previous_syncing_offset_ = block.offset; + num_bits_since_sync_lost_ = 0; } } } @@ -293,4 +293,8 @@ Group BlockStream::flushCurrentGroup() const { return current_group_; } +size_t BlockStream::getNumBitsSinceSyncLost() const { + return num_bits_since_sync_lost_; +} + } // namespace redsea diff --git a/src/block_sync.h b/src/block_sync.h index a961101..76e9518 100644 --- a/src/block_sync.h +++ b/src/block_sync.h @@ -51,8 +51,8 @@ class BlockStream { void pushBit(bool bit); Group popGroup(); bool hasGroupReady() const; - bool eof() const; Group flushCurrentGroup() const; + size_t getNumBitsSinceSyncLost() const; private: void acquireSync(Block block); @@ -61,19 +61,17 @@ class BlockStream { void handleNewlyReceivedGroup(); int bitcount_ { 0 }; - int previous_syncing_bitcount_ { 0 }; int num_bits_until_next_block_ { 1 }; uint32_t input_register_ { 0 }; - Offset previous_syncing_offset_ { Offset::invalid }; Offset expected_offset_ { Offset::A }; bool is_in_sync_ { false }; RunningSum block_error_sum50_; const Options options_; - bool is_eof_ { false }; RunningAverage bler_average_; Group current_group_; Group ready_group_; bool has_group_ready_ { false }; + size_t num_bits_since_sync_lost_ { 0 }; }; } // namespace redsea diff --git a/src/channel.cc b/src/channel.cc index f66c3b8..62545f0 100644 --- a/src/channel.cc +++ b/src/channel.cc @@ -133,4 +133,8 @@ void Channel::flush() { processGroup(last_group); } +float Channel::getSecondsSinceCarrierLost() const { + return block_stream_.getNumBitsSinceSyncLost() / kBitsPerSecond; +} + } // namespace redsea diff --git a/src/channel.h b/src/channel.h index 26ff474..2bd2201 100644 --- a/src/channel.h +++ b/src/channel.h @@ -65,6 +65,7 @@ class Channel { void processBits(BitBuffer buffer); void processGroup(Group group); void flush(); + float getSecondsSinceCarrierLost() const; private: Options options_; diff --git a/src/common.h b/src/common.h index f542953..1718a5a 100644 --- a/src/common.h +++ b/src/common.h @@ -23,12 +23,12 @@ namespace redsea { -constexpr float kTargetSampleRate_Hz = 171000.0f; -constexpr int kNumBlerAverageGroups = 12; +constexpr float kBitsPerSecond = 1187.5f; constexpr float kMinimumSampleRate_Hz = 128000.0f; +constexpr int kNumBlerAverageGroups = 12; +constexpr float kTargetSampleRate_Hz = 171000.0f; -class BitBuffer { - public: +struct BitBuffer { std::chrono::time_point time_received; std::vector bits; }; diff --git a/src/liquid_wrappers.cc b/src/liquid_wrappers.cc index 4755cc2..badcbaa 100644 --- a/src/liquid_wrappers.cc +++ b/src/liquid_wrappers.cc @@ -66,7 +66,7 @@ size_t FIRFilter::length() const { } NCO::NCO(liquid_ncotype type, float freq) : - object_(nco_crcf_create(type)) { + object_(nco_crcf_create(type)), initial_frequency_(freq) { nco_crcf_set_frequency(object_, freq); } @@ -74,6 +74,11 @@ NCO::~NCO() { nco_crcf_destroy(object_); } +void NCO::reset() { + nco_crcf_reset(object_); + nco_crcf_set_frequency(object_, initial_frequency_); +} + std::complex NCO::mixDown(std::complex s) { std::complex result; nco_crcf_mix_down(object_, s, &result); @@ -92,6 +97,10 @@ void NCO::stepPLL(float dphi) { nco_crcf_pll_step(object_, dphi); } +float NCO::getFrequency() { + return nco_crcf_get_frequency(object_); +} + SymSync::SymSync(liquid_firfilt_type ftype, unsigned k, unsigned m, float beta, unsigned num_filters) : object_(symsync_crcf_create_rnyquist(ftype, k, m, beta, num_filters)), @@ -102,6 +111,10 @@ SymSync::~SymSync() { symsync_crcf_destroy(object_); } +void SymSync::reset() { + symsync_crcf_reset(object_); +} + void SymSync::setBandwidth(float bw) { symsync_crcf_set_lf_bw(object_, bw); } diff --git a/src/liquid_wrappers.h b/src/liquid_wrappers.h index 88d4217..ec71d2c 100644 --- a/src/liquid_wrappers.h +++ b/src/liquid_wrappers.h @@ -60,16 +60,19 @@ class FIRFilter { class NCO { public: - explicit NCO(liquid_ncotype type, float freq); + NCO(liquid_ncotype type, float freq); NCO(const NCO&) = delete; ~NCO(); std::complex mixDown(std::complex s); void step(); void setPLLBandwidth(float); void stepPLL(float dphi); + void reset(); + float getFrequency(); private: nco_crcf object_; + float initial_frequency_; }; class SymSync { @@ -78,6 +81,7 @@ class SymSync { float beta, unsigned num_filters); SymSync(const SymSync&) = delete; ~SymSync(); + void reset(); void setBandwidth(float); void setOutputRate(unsigned); Maybe> execute(std::complex* in); diff --git a/src/redsea.cc b/src/redsea.cc index 0a71d6e..bea11d2 100644 --- a/src/redsea.cc +++ b/src/redsea.cc @@ -133,6 +133,10 @@ int processMPXInput(Options options) { channels[i].processBits( subcarriers[i]->processChunk(mpx.readChunk(int(i))) ); + if (channels[i].getSecondsSinceCarrierLost() > 10.f && + subcarriers[i]->getSecondsSinceLastReset() > 5.f) { + subcarriers[i]->reset(); + } } } diff --git a/src/subcarrier.cc b/src/subcarrier.cc index 3f8856c..42594e0 100644 --- a/src/subcarrier.cc +++ b/src/subcarrier.cc @@ -36,7 +36,6 @@ namespace redsea { namespace { constexpr float kCarrierFrequency_Hz = 57000.0f; -constexpr float kBitsPerSecond = 1187.5f; constexpr int kSamplesPerSymbol = 3; constexpr float kAGCBandwidth_Hz = 500.0f; constexpr float kAGCInitialGain = 0.08f; @@ -113,6 +112,12 @@ Subcarrier::Subcarrier(const Options& options) : oscillator_.setPLLBandwidth(kPLLBandwidth_Hz / kTargetSampleRate_Hz); } +void Subcarrier::reset() { + symsync_.reset(); + oscillator_.reset(); + sample_num_ = 0; +} + /** MPX to bits */ BitBuffer Subcarrier::processChunk(MPXBuffer<>& chunk) { @@ -179,6 +184,10 @@ bool Subcarrier::eof() const { return is_eof_; } +float Subcarrier::getSecondsSinceLastReset() const { + return sample_num_ / kTargetSampleRate_Hz; +} + } // namespace redsea #endif // HAVE_LIQUID diff --git a/src/subcarrier.h b/src/subcarrier.h index 2336d19..3b42303 100644 --- a/src/subcarrier.h +++ b/src/subcarrier.h @@ -62,6 +62,8 @@ class Subcarrier { ~Subcarrier() = default; bool eof() const; BitBuffer processChunk(MPXBuffer<>& chunk); + void reset(); + float getSecondsSinceLastReset() const; private: int sample_num_ { 0 };