Skip to content

Commit

Permalink
Reset modem if carrier lost (#94)
Browse files Browse the repository at this point in the history
When carrier is lost the PLL keeps looking for it and starts drifting
slowly. This can make it harder to lock on to the carrier when it
comes back. One solution is to reset the frequency back to 57 Khz
after 10 seconds of loss of block sync being detected.

Open question: is the PLL interface being used correctly?
  • Loading branch information
windytan committed Aug 27, 2023
1 parent 9587d69 commit 748356b
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 14 deletions.
10 changes: 7 additions & 3 deletions src/block_sync.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_);
Expand All @@ -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;
}
}
}
Expand Down Expand Up @@ -293,4 +293,8 @@ Group BlockStream::flushCurrentGroup() const {
return current_group_;
}

size_t BlockStream::getNumBitsSinceSyncLost() const {
return num_bits_since_sync_lost_;
}

} // namespace redsea
6 changes: 2 additions & 4 deletions src/block_sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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<int, 50> block_error_sum50_;
const Options options_;
bool is_eof_ { false };
RunningAverage<float, kNumBlerAverageGroups> bler_average_;
Group current_group_;
Group ready_group_;
bool has_group_ready_ { false };
size_t num_bits_since_sync_lost_ { 0 };
};

} // namespace redsea
Expand Down
4 changes: 4 additions & 0 deletions src/channel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,8 @@ void Channel::flush() {
processGroup(last_group);
}

float Channel::getSecondsSinceCarrierLost() const {
return block_stream_.getNumBitsSinceSyncLost() / kBitsPerSecond;
}

} // namespace redsea
1 change: 1 addition & 0 deletions src/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class Channel {
void processBits(BitBuffer buffer);
void processGroup(Group group);
void flush();
float getSecondsSinceCarrierLost() const;

private:
Options options_;
Expand Down
8 changes: 4 additions & 4 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::chrono::system_clock> time_received;
std::vector<bool> bits;
};
Expand Down
15 changes: 14 additions & 1 deletion src/liquid_wrappers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,19 @@ 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);
}

NCO::~NCO() {
nco_crcf_destroy(object_);
}

void NCO::reset() {
nco_crcf_reset(object_);
nco_crcf_set_frequency(object_, initial_frequency_);
}

std::complex<float> NCO::mixDown(std::complex<float> s) {
std::complex<float> result;
nco_crcf_mix_down(object_, s, &result);
Expand All @@ -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)),
Expand All @@ -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);
}
Expand Down
6 changes: 5 additions & 1 deletion src/liquid_wrappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<float> mixDown(std::complex<float> s);
void step();
void setPLLBandwidth(float);
void stepPLL(float dphi);
void reset();
float getFrequency();

private:
nco_crcf object_;
float initial_frequency_;
};

class SymSync {
Expand All @@ -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<std::complex<float>> execute(std::complex<float>* in);
Expand Down
4 changes: 4 additions & 0 deletions src/redsea.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/subcarrier.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
2 changes: 2 additions & 0 deletions src/subcarrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down

0 comments on commit 748356b

Please sign in to comment.