Pilot PPS logging works.
This commit is contained in:
		
							parent
							
								
									f6bca05bf0
								
							
						
					
					
						commit
						6d735bb0f0
					
				|  | @ -219,9 +219,9 @@ void PilotPhaseLock::process(const SampleVector& samples_in, | ||||||
|                 m_pilot_periods = 0; |                 m_pilot_periods = 0; | ||||||
|                 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 | ||||||
|  |  | ||||||
							
								
								
									
										68
									
								
								main.cc
								
								
								
								
							
							
						
						
									
										68
									
								
								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" | ||||||
|  | @ -212,7 +213,7 @@ static void handle_sigterm(int sig) | ||||||
| void usage() | void usage() | ||||||
| { | { | ||||||
|     fprintf(stderr, |     fprintf(stderr, | ||||||
|             "Usage: softfm -f freq [options]\n" |     "Usage: softfm -f freq [options]\n" | ||||||
|             "  -f freq       Frequency of radio station in Hz\n" |             "  -f freq       Frequency of radio station in Hz\n" | ||||||
|             "  -d devidx     RTL-SDR device index, 'list' to show device list (default 0)\n" |             "  -d devidx     RTL-SDR device index, 'list' to show device list (default 0)\n" | ||||||
|             "  -s ifrate     IF sample rate in Hz (default 1000000, min 900001)\n" |             "  -s ifrate     IF sample rate in Hz (default 1000000, min 900001)\n" | ||||||
|  | @ -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