Prepare pilot PLL to produce PPS events.
This commit is contained in:
parent
cfc5e07db6
commit
f6bca05bf0
35
FmDecode.cc
35
FmDecode.cc
|
@ -134,6 +134,11 @@ PilotPhaseLock::PilotPhaseLock(double freq, double bandwidth, double minsignal)
|
||||||
m_phasor_q1 = 0;
|
m_phasor_q1 = 0;
|
||||||
m_phasor_q2 = 0;
|
m_phasor_q2 = 0;
|
||||||
m_loopfilter_x1 = 0;
|
m_loopfilter_x1 = 0;
|
||||||
|
|
||||||
|
// Initialize PPS generator.
|
||||||
|
m_pilot_periods = 0;
|
||||||
|
m_pps_cnt = 0;
|
||||||
|
m_sample_cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,6 +150,9 @@ void PilotPhaseLock::process(const SampleVector& samples_in,
|
||||||
|
|
||||||
samples_out.resize(n);
|
samples_out.resize(n);
|
||||||
|
|
||||||
|
bool was_locked = (m_lock_cnt >= m_lock_delay);
|
||||||
|
m_pps_events.clear();
|
||||||
|
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
m_pilot_level = 1000.0;
|
m_pilot_level = 1000.0;
|
||||||
|
|
||||||
|
@ -202,8 +210,23 @@ void PilotPhaseLock::process(const SampleVector& samples_in,
|
||||||
|
|
||||||
// Update locked phase.
|
// Update locked phase.
|
||||||
m_phase += m_freq;
|
m_phase += m_freq;
|
||||||
if (m_phase > 2.0 * M_PI)
|
if (m_phase > 2.0 * M_PI) {
|
||||||
m_phase -= 2.0 * M_PI;
|
m_phase -= 2.0 * M_PI;
|
||||||
|
m_pilot_periods++;
|
||||||
|
|
||||||
|
// Generate pulse-per-second.
|
||||||
|
if (m_pilot_periods == pilot_frequency) {
|
||||||
|
m_pilot_periods = 0;
|
||||||
|
if (was_locked) {
|
||||||
|
struct PpsEvent ev;
|
||||||
|
ev.pps_index = m_pps_cnt;
|
||||||
|
ev.abs_sample_index = m_sample_cnt + i;
|
||||||
|
ev.block_sample_index = i;
|
||||||
|
m_pps_events.push_back(ev);
|
||||||
|
m_pps_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update lock status.
|
// Update lock status.
|
||||||
|
@ -213,6 +236,16 @@ void PilotPhaseLock::process(const SampleVector& samples_in,
|
||||||
} else {
|
} else {
|
||||||
m_lock_cnt = 0;
|
m_lock_cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drop PPS events when pilot not locked.
|
||||||
|
if (m_lock_cnt < m_lock_delay) {
|
||||||
|
m_pilot_periods = 0;
|
||||||
|
m_pps_cnt = 0;
|
||||||
|
m_pps_events.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update sample counter.
|
||||||
|
m_sample_cnt += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
30
FmDecode.h
30
FmDecode.h
|
@ -1,6 +1,9 @@
|
||||||
#ifndef SOFTFM_FMDECODE_H
|
#ifndef SOFTFM_FMDECODE_H
|
||||||
#define SOFTFM_FMDECODE_H
|
#define SOFTFM_FMDECODE_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "SoftFM.h"
|
#include "SoftFM.h"
|
||||||
#include "Filter.h"
|
#include "Filter.h"
|
||||||
|
|
||||||
|
@ -36,7 +39,16 @@ class PilotPhaseLock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// TODO : pulse-per-second
|
/** Expected pilot frequency (used for PPS events). */
|
||||||
|
static constexpr int pilot_frequency = 19000;
|
||||||
|
|
||||||
|
/** Timestamp event produced once every 19000 pilot periods. */
|
||||||
|
struct PpsEvent
|
||||||
|
{
|
||||||
|
std::uint64_t pps_index;
|
||||||
|
std::uint64_t abs_sample_index;
|
||||||
|
std::uint64_t block_sample_index;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct phase-locked loop.
|
* Construct phase-locked loop.
|
||||||
|
@ -66,6 +78,12 @@ public:
|
||||||
return 2 * m_pilot_level;
|
return 2 * m_pilot_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return PPS events from the most recently processed block. */
|
||||||
|
std::vector<PpsEvent> get_pps_events() const
|
||||||
|
{
|
||||||
|
return m_pps_events;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Sample m_minfreq, m_maxfreq;
|
Sample m_minfreq, m_maxfreq;
|
||||||
Sample m_phasor_b0, m_phasor_a1, m_phasor_a2;
|
Sample m_phasor_b0, m_phasor_a1, m_phasor_a2;
|
||||||
|
@ -77,6 +95,10 @@ private:
|
||||||
Sample m_pilot_level;
|
Sample m_pilot_level;
|
||||||
int m_lock_delay;
|
int m_lock_delay;
|
||||||
int m_lock_cnt;
|
int m_lock_cnt;
|
||||||
|
int m_pilot_periods;
|
||||||
|
std::uint64_t m_pps_cnt;
|
||||||
|
std::uint64_t m_sample_cnt;
|
||||||
|
std::vector<PpsEvent> m_pps_events;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,6 +185,12 @@ public:
|
||||||
return m_pilotpll.get_pilot_level();
|
return m_pilotpll.get_pilot_level();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return PPS events from the most recently processed block. */
|
||||||
|
std::vector<PilotPhaseLock::PpsEvent> get_pps_events() const
|
||||||
|
{
|
||||||
|
return m_pilotpll.get_pps_events();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Demodulate stereo L-R signal. */
|
/** Demodulate stereo L-R signal. */
|
||||||
void demod_stereo(const SampleVector& samples_baseband,
|
void demod_stereo(const SampleVector& samples_baseband,
|
||||||
|
|
Loading…
Reference in New Issue