mirror of
https://github.com/rtlsdrblog/rtl-sdr-blog.git
synced 2024-12-26 02:48:31 +01:00
rtl_fm: broken multi freq scanning
Signed-off-by: Steve Markgraf <steve@steve-m.de>
This commit is contained in:
parent
6a9f5c14c2
commit
defa7af74b
120
src/rtl_fm.c
120
src/rtl_fm.c
@ -27,6 +27,7 @@
|
|||||||
* in-place array operations
|
* in-place array operations
|
||||||
* wide band support
|
* wide band support
|
||||||
* refactor to look like rtl_tcp
|
* refactor to look like rtl_tcp
|
||||||
|
* multiple frequency scanning
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -55,18 +56,23 @@ static rtlsdr_dev_t *dev = NULL;
|
|||||||
|
|
||||||
struct fm_state
|
struct fm_state
|
||||||
{
|
{
|
||||||
int now_r;
|
int now_r;
|
||||||
int now_j;
|
int now_j;
|
||||||
int pre_r;
|
int pre_r;
|
||||||
int pre_j;
|
int pre_j;
|
||||||
int prev_index;
|
int prev_index;
|
||||||
int downsample; /* min 4, max 256 */
|
int downsample; /* min 4, max 256 */
|
||||||
int output_scale;
|
int output_scale;
|
||||||
int squelch_level;
|
int squelch_level;
|
||||||
int signal[2048]; /* 16 bit signed i/q pairs */
|
int signal[2048]; /* 16 bit signed i/q pairs */
|
||||||
int16_t signal2[2048]; /* signal has lowpass, signal2 has demod */
|
int16_t signal2[2048]; /* signal has lowpass, signal2 has demod */
|
||||||
int signal_len;
|
int signal_len;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
|
int edge;
|
||||||
|
uint32_t freqs[32];
|
||||||
|
int freq_len;
|
||||||
|
int freq_now;
|
||||||
|
uint32_t sample_rate;
|
||||||
};
|
};
|
||||||
|
|
||||||
void usage(void)
|
void usage(void)
|
||||||
@ -79,6 +85,7 @@ void usage(void)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"rtl_fm, a simple narrow band FM demodulator for RTL2832 based DVB-T receivers\n\n"
|
"rtl_fm, a simple narrow band FM demodulator for RTL2832 based DVB-T receivers\n\n"
|
||||||
"Usage:\t -f frequency_to_tune_to [Hz]\n"
|
"Usage:\t -f frequency_to_tune_to [Hz]\n"
|
||||||
|
"\t (use multiple -f for scanning !!BROKEN!!)\n"
|
||||||
"\t[-s samplerate (default: 24000 Hz)]\n"
|
"\t[-s samplerate (default: 24000 Hz)]\n"
|
||||||
"\t[-d device_index (default: 0)]\n"
|
"\t[-d device_index (default: 0)]\n"
|
||||||
"\t[-g tuner_gain (default: -1dB)]\n"
|
"\t[-g tuner_gain (default: -1dB)]\n"
|
||||||
@ -203,7 +210,8 @@ int mad(int *samples, int len, int step)
|
|||||||
return sum / (len * step);
|
return sum / (len * step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void post_squelch(struct fm_state *fm)
|
int post_squelch(struct fm_state *fm)
|
||||||
|
/* returns 1 for active signal, 0 for no signal */
|
||||||
{
|
{
|
||||||
int i, i2, dev_r, dev_j, len, sq_l;
|
int i, i2, dev_r, dev_j, len, sq_l;
|
||||||
/* only for small samples, big samples need chunk processing */
|
/* only for small samples, big samples need chunk processing */
|
||||||
@ -212,17 +220,48 @@ void post_squelch(struct fm_state *fm)
|
|||||||
dev_r = mad(&(fm->signal[0]), len, 2);
|
dev_r = mad(&(fm->signal[0]), len, 2);
|
||||||
dev_j = mad(&(fm->signal[1]), len, 2);
|
dev_j = mad(&(fm->signal[1]), len, 2);
|
||||||
if ((dev_r > sq_l) || (dev_j > sq_l)) {
|
if ((dev_r > sq_l) || (dev_j > sq_l)) {
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
/* weak signal, kill it entirely */
|
/* weak signal, kill it entirely */
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
fm->signal2[i/2] = 0;
|
fm->signal2[i/2] = 0;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void optimal_settings(struct fm_state *fm, int freq, int hopping)
|
||||||
|
{
|
||||||
|
int r, capture_freq, capture_rate;
|
||||||
|
fm->downsample = (1000000 / fm->sample_rate) + 1;
|
||||||
|
fm->freq_now = freq;
|
||||||
|
capture_rate = fm->downsample * fm->sample_rate;
|
||||||
|
capture_freq = fm->freqs[freq] + capture_rate/4;
|
||||||
|
capture_freq += fm->edge * fm->sample_rate / 2;
|
||||||
|
fm->output_scale = (1<<15) / (128 * fm->downsample);
|
||||||
|
if (fm->output_scale < 1) {
|
||||||
|
fm->output_scale = 1;}
|
||||||
|
fm->output_scale = 1;
|
||||||
|
/* Set the frequency */
|
||||||
|
r = rtlsdr_set_center_freq(dev, capture_freq);
|
||||||
|
if (hopping) {
|
||||||
|
return;}
|
||||||
|
fprintf(stderr, "Oversampling by: %ix.\n", fm->downsample);
|
||||||
|
if (r < 0) {
|
||||||
|
fprintf(stderr, "WARNING: Failed to set center freq.\n");}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Tuned to %u Hz.\n", capture_freq);}
|
||||||
|
|
||||||
|
/* Set the sample rate */
|
||||||
|
r = rtlsdr_set_sample_rate(dev, capture_rate);
|
||||||
|
if (r < 0) {
|
||||||
|
fprintf(stderr, "WARNING: Failed to set sample rate.\n");}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
|
static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
|
||||||
{
|
{
|
||||||
struct fm_state *fm2;
|
struct fm_state *fm2;
|
||||||
|
int sr, freq_next;
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -230,34 +269,18 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
|
|||||||
rotate_90(buf, len);
|
rotate_90(buf, len);
|
||||||
low_pass(fm2, buf, len);
|
low_pass(fm2, buf, len);
|
||||||
fm_demod(fm2);
|
fm_demod(fm2);
|
||||||
post_squelch(fm2);
|
sr = post_squelch(fm2);
|
||||||
/* ignore under runs for now */
|
/* ignore under runs for now */
|
||||||
fwrite(fm2->signal2, 2, fm2->signal_len/2, fm2->file);
|
fwrite(fm2->signal2, 2, fm2->signal_len/2, fm2->file);
|
||||||
}
|
if (fm2->freq_len > 1 && !sr) {
|
||||||
|
freq_next = (fm2->freq_now + 1) % fm2->freq_len;
|
||||||
static void optimal_settings(struct fm_state *fm, int freq, int rate, int edge)
|
optimal_settings(fm2, freq_next, 1);
|
||||||
{
|
rtlsdr_reset_buffer(dev);
|
||||||
int r, capture_freq, capture_rate;
|
//rtlsdr_read_async(dev, rtlsdr_callback, ctx,
|
||||||
fm->downsample = (1000000 / rate) + 1;
|
// DEFAULT_ASYNC_BUF_NUMBER, DEFAULT_BUF_LENGTH);
|
||||||
fprintf(stderr, "Oversampling by: %ix.\n", fm->downsample);
|
//rtlsdr_wait_async(dev, rtlsdr_callback, (void *)0);
|
||||||
capture_rate = fm->downsample * rate;
|
//rtlsdr_wait_async(dev, rtlsdr_callback, ctx);
|
||||||
capture_freq = (freq + (edge*rate/2)) + capture_rate/4;
|
|
||||||
fm->output_scale = (1<<15) / (128 * fm->downsample);
|
|
||||||
if (fm->output_scale < 1) {
|
|
||||||
fm->output_scale = 1;
|
|
||||||
}
|
}
|
||||||
fm->output_scale = 1;
|
|
||||||
/* Set the sample rate */
|
|
||||||
r = rtlsdr_set_sample_rate(dev, capture_rate);
|
|
||||||
if (r < 0)
|
|
||||||
fprintf(stderr, "WARNING: Failed to set sample rate.\n");
|
|
||||||
|
|
||||||
/* Set the frequency */
|
|
||||||
r = rtlsdr_set_center_freq(dev, capture_freq);
|
|
||||||
if (r < 0)
|
|
||||||
fprintf(stderr, "WARNING: Failed to set center freq.\n");
|
|
||||||
else
|
|
||||||
fprintf(stderr, "Tuned to %u Hz.\n", capture_freq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
@ -269,15 +292,16 @@ int main(int argc, char **argv)
|
|||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
int n_read;
|
int n_read;
|
||||||
int r, opt;
|
int r, opt;
|
||||||
int i, edge = 0, gain = -10; // tenths of a dB
|
int i, gain = -10; // tenths of a dB
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
uint32_t dev_index = 0;
|
uint32_t dev_index = 0;
|
||||||
uint32_t frequency = 100000000;
|
|
||||||
uint32_t samp_rate = DEFAULT_SAMPLE_RATE;
|
|
||||||
uint32_t out_block_size = DEFAULT_BUF_LENGTH;
|
uint32_t out_block_size = DEFAULT_BUF_LENGTH;
|
||||||
int device_count;
|
int device_count;
|
||||||
char vendor[256], product[256], serial[256];
|
char vendor[256], product[256], serial[256];
|
||||||
|
fm.freqs[0] = 100000000;
|
||||||
|
fm.sample_rate = DEFAULT_SAMPLE_RATE;
|
||||||
fm.squelch_level = 150;
|
fm.squelch_level = 150;
|
||||||
|
fm.freq_len = 0;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
while ((opt = getopt(argc, argv, "d:f:g:s:b:l:E::")) != -1) {
|
while ((opt = getopt(argc, argv, "d:f:g:s:b:l:E::")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@ -285,7 +309,8 @@ int main(int argc, char **argv)
|
|||||||
dev_index = atoi(optarg);
|
dev_index = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
frequency = (uint32_t)atof(optarg);
|
fm.freqs[fm.freq_len] = (uint32_t)atof(optarg);
|
||||||
|
fm.freq_len++;
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
gain = (int)(atof(optarg) * 10);
|
gain = (int)(atof(optarg) * 10);
|
||||||
@ -294,10 +319,10 @@ int main(int argc, char **argv)
|
|||||||
fm.squelch_level = (int)atof(optarg);
|
fm.squelch_level = (int)atof(optarg);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
samp_rate = (uint32_t)atof(optarg);
|
fm.sample_rate = (uint32_t)atof(optarg);
|
||||||
break;
|
break;
|
||||||
case 'E':
|
case 'E':
|
||||||
edge = 1;
|
fm.edge = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
@ -316,7 +341,8 @@ int main(int argc, char **argv)
|
|||||||
dev_index = atoi(argv[1]);
|
dev_index = atoi(argv[1]);
|
||||||
samp_rate = atoi(argv[2])*1000;
|
samp_rate = atoi(argv[2])*1000;
|
||||||
gain=(int)(atof(argv[3]) * 10);
|
gain=(int)(atof(argv[3]) * 10);
|
||||||
frequency = atoi(argv[4]);
|
fm.freqs[0] = atoi(argv[4]);
|
||||||
|
fm.freq_len = 1;
|
||||||
filename = argv[5];
|
filename = argv[5];
|
||||||
#endif
|
#endif
|
||||||
out_block_size = DEFAULT_BUF_LENGTH;
|
out_block_size = DEFAULT_BUF_LENGTH;
|
||||||
@ -356,7 +382,7 @@ int main(int argc, char **argv)
|
|||||||
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
|
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
optimal_settings(&fm, frequency, samp_rate, edge);
|
optimal_settings(&fm, 0, 0);
|
||||||
|
|
||||||
/* Set the tuner gain */
|
/* Set the tuner gain */
|
||||||
r = rtlsdr_set_tuner_gain(dev, gain);
|
r = rtlsdr_set_tuner_gain(dev, gain);
|
||||||
|
Loading…
Reference in New Issue
Block a user