Pilot PPS logging works.
This commit is contained in:
parent
f6bca05bf0
commit
6d735bb0f0
|
@ -220,8 +220,8 @@ void PilotPhaseLock::process(const SampleVector& samples_in,
|
||||||
if (was_locked) {
|
if (was_locked) {
|
||||||
struct PpsEvent ev;
|
struct PpsEvent ev;
|
||||||
ev.pps_index = m_pps_cnt;
|
ev.pps_index = m_pps_cnt;
|
||||||
ev.abs_sample_index = m_sample_cnt + i;
|
ev.sample_index = m_sample_cnt + i;
|
||||||
ev.block_sample_index = i;
|
ev.block_position = double(i) / double(n);
|
||||||
m_pps_events.push_back(ev);
|
m_pps_events.push_back(ev);
|
||||||
m_pps_cnt++;
|
m_pps_cnt++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,8 +46,8 @@ public:
|
||||||
struct PpsEvent
|
struct PpsEvent
|
||||||
{
|
{
|
||||||
std::uint64_t pps_index;
|
std::uint64_t pps_index;
|
||||||
std::uint64_t abs_sample_index;
|
std::uint64_t sample_index;
|
||||||
std::uint64_t block_sample_index;
|
double block_position;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
1
TODO.txt
1
TODO.txt
|
@ -1,4 +1,3 @@
|
||||||
* (feature) implement stereo pilot pulse-per-second
|
|
||||||
* (speedup) maybe replace high-order FIR downsampling filter with 2nd order butterworth followed by lower order FIR filter
|
* (speedup) maybe replace high-order FIR downsampling filter with 2nd order butterworth followed by lower order FIR filter
|
||||||
* figure out why we sometimes lose stereo lock
|
* figure out why we sometimes lose stereo lock
|
||||||
* (feature) implement RDS decoding
|
* (feature) implement RDS decoding
|
||||||
|
|
66
main.cc
66
main.cc
|
@ -31,6 +31,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "SoftFM.h"
|
#include "SoftFM.h"
|
||||||
#include "RtlSdrSource.h"
|
#include "RtlSdrSource.h"
|
||||||
|
@ -223,6 +224,8 @@ void usage()
|
||||||
" use filename '-' to write to stdout\n"
|
" use filename '-' to write to stdout\n"
|
||||||
" -W filename Write audio data to .WAV file\n"
|
" -W filename Write audio data to .WAV file\n"
|
||||||
" -P [device] Play audio via ALSA device (default 'default')\n"
|
" -P [device] Play audio via ALSA device (default 'default')\n"
|
||||||
|
" -T filename Write pulse-per-second timestamps\n"
|
||||||
|
" use filename '-' to write to stdout\n"
|
||||||
" -b seconds Set audio buffer size in seconds\n"
|
" -b seconds Set audio buffer size in seconds\n"
|
||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
@ -274,6 +277,15 @@ bool parse_dbl(const char *s, double& v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Return Unix time stamp in seconds. */
|
||||||
|
double get_time()
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return tv.tv_sec + 1.0e-6 * tv.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
double freq = -1;
|
double freq = -1;
|
||||||
|
@ -285,6 +297,8 @@ int main(int argc, char **argv)
|
||||||
OutputMode outmode = MODE_ALSA;
|
OutputMode outmode = MODE_ALSA;
|
||||||
string filename;
|
string filename;
|
||||||
string alsadev("default");
|
string alsadev("default");
|
||||||
|
string ppsfilename;
|
||||||
|
FILE * ppsfile = NULL;
|
||||||
double bufsecs = -1;
|
double bufsecs = -1;
|
||||||
int agcmode = 1;
|
int agcmode = 1;
|
||||||
|
|
||||||
|
@ -301,12 +315,13 @@ int main(int argc, char **argv)
|
||||||
{ "raw", 1, NULL, 'R' },
|
{ "raw", 1, NULL, 'R' },
|
||||||
{ "wav", 1, NULL, 'W' },
|
{ "wav", 1, NULL, 'W' },
|
||||||
{ "play", 2, NULL, 'P' },
|
{ "play", 2, NULL, 'P' },
|
||||||
|
{ "pps", 1, NULL, 'T' },
|
||||||
{ "buffer", 1, NULL, 'b' },
|
{ "buffer", 1, NULL, 'b' },
|
||||||
{ NULL, 0, NULL, 0 } };
|
{ NULL, 0, NULL, 0 } };
|
||||||
|
|
||||||
int c, longindex;
|
int c, longindex;
|
||||||
while ((c = getopt_long(argc, argv,
|
while ((c = getopt_long(argc, argv,
|
||||||
"f:d:s:r:MR:W:P::b:a:",
|
"f:d:s:r:MR:W:P::T:b:a:",
|
||||||
longopts, &longindex)) >= 0) {
|
longopts, &longindex)) >= 0) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'f':
|
case 'f':
|
||||||
|
@ -345,6 +360,9 @@ int main(int argc, char **argv)
|
||||||
if (optarg != NULL)
|
if (optarg != NULL)
|
||||||
alsadev = optarg;
|
alsadev = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
ppsfilename = optarg;
|
||||||
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
if (!parse_dbl(optarg, bufsecs) || bufsecs < 0) {
|
if (!parse_dbl(optarg, bufsecs) || bufsecs < 0) {
|
||||||
badarg("-b");
|
badarg("-b");
|
||||||
|
@ -469,6 +487,25 @@ int main(int argc, char **argv)
|
||||||
outputbuf_samples / double(pcmrate));
|
outputbuf_samples / double(pcmrate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open PPS file.
|
||||||
|
if (!ppsfilename.empty()) {
|
||||||
|
if (ppsfilename == "-") {
|
||||||
|
fprintf(stderr, "Writing pulse-per-second markers to stdout\n");
|
||||||
|
ppsfile = stdout;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Writing pulse-per-second markers to '%s'\n",
|
||||||
|
ppsfilename.c_str());
|
||||||
|
ppsfile = fopen(ppsfilename.c_str(), "w");
|
||||||
|
if (ppsfile == NULL) {
|
||||||
|
fprintf(stderr, "ERROR: can not open '%s' (%s)\n",
|
||||||
|
ppsfilename.c_str(), strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(ppsfile, "#pps_index sample_index unix_time\n");
|
||||||
|
fflush(ppsfile);
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare output writer.
|
// Prepare output writer.
|
||||||
unique_ptr<AudioOutput> audio_output;
|
unique_ptr<AudioOutput> audio_output;
|
||||||
switch (outmode) {
|
switch (outmode) {
|
||||||
|
@ -511,6 +548,8 @@ int main(int argc, char **argv)
|
||||||
double audio_level = 0;
|
double audio_level = 0;
|
||||||
bool got_stereo = false;
|
bool got_stereo = false;
|
||||||
|
|
||||||
|
double block_time = get_time();
|
||||||
|
|
||||||
// Main loop.
|
// Main loop.
|
||||||
for (unsigned int block = 0; !stop_flag.load(); block++) {
|
for (unsigned int block = 0; !stop_flag.load(); block++) {
|
||||||
|
|
||||||
|
@ -527,6 +566,9 @@ int main(int argc, char **argv)
|
||||||
if (iqsamples.empty())
|
if (iqsamples.empty())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
double prev_block_time = block_time;
|
||||||
|
block_time = get_time();
|
||||||
|
|
||||||
// Decode FM signal.
|
// Decode FM signal.
|
||||||
fm.process(iqsamples, audiosamples);
|
fm.process(iqsamples, audiosamples);
|
||||||
|
|
||||||
|
@ -535,10 +577,10 @@ int main(int argc, char **argv)
|
||||||
samples_mean_rms(audiosamples, audio_mean, audio_rms);
|
samples_mean_rms(audiosamples, audio_mean, audio_rms);
|
||||||
audio_level = 0.95 * audio_level + 0.05 * audio_rms;
|
audio_level = 0.95 * audio_level + 0.05 * audio_rms;
|
||||||
|
|
||||||
|
// Set nominal audio volume.
|
||||||
adjust_gain(audiosamples, 0.5);
|
adjust_gain(audiosamples, 0.5);
|
||||||
|
|
||||||
// TODO : investigate I/Q imbalance to fix Radio4 noise
|
// Show statistics.
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\rblk=%6d freq=%8.4fMHz IF=%+5.1fdB BB=%+5.1fdB audio=%+5.1fdB ",
|
"\rblk=%6d freq=%8.4fMHz IF=%+5.1fdB BB=%+5.1fdB audio=%+5.1fdB ",
|
||||||
block,
|
block,
|
||||||
|
@ -555,6 +597,7 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
|
// Show stereo status.
|
||||||
if (fm.stereo_detected() != got_stereo) {
|
if (fm.stereo_detected() != got_stereo) {
|
||||||
got_stereo = fm.stereo_detected();
|
got_stereo = fm.stereo_detected();
|
||||||
if (got_stereo)
|
if (got_stereo)
|
||||||
|
@ -564,6 +607,23 @@ int main(int argc, char **argv)
|
||||||
fprintf(stderr, "\nlost stereo signal\n");
|
fprintf(stderr, "\nlost stereo signal\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write PPS markers.
|
||||||
|
if (ppsfile != NULL) {
|
||||||
|
for (const PilotPhaseLock::PpsEvent& ev : fm.get_pps_events()) {
|
||||||
|
double ts = prev_block_time;
|
||||||
|
ts += ev.block_position * (block_time - prev_block_time);
|
||||||
|
if (ppsfile == stdout && isatty(fileno(ppsfile))) {
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
fprintf(ppsfile, "%8s %14s %18.6f\n",
|
||||||
|
to_string(ev.pps_index).c_str(),
|
||||||
|
to_string(ev.sample_index).c_str(),
|
||||||
|
ts);
|
||||||
|
fflush(ppsfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Throw away first block. It is noisy because IF filters
|
// Throw away first block. It is noisy because IF filters
|
||||||
// are still starting up.
|
// are still starting up.
|
||||||
if (block > 0) {
|
if (block > 0) {
|
||||||
|
|
Loading…
Reference in New Issue