mirror of
https://github.com/rtlsdrblog/rtl-sdr-blog.git
synced 2024-12-25 10:28:28 +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
|
||||
* wide band support
|
||||
* refactor to look like rtl_tcp
|
||||
* multiple frequency scanning
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
@ -55,18 +56,23 @@ static rtlsdr_dev_t *dev = NULL;
|
||||
|
||||
struct fm_state
|
||||
{
|
||||
int now_r;
|
||||
int now_j;
|
||||
int pre_r;
|
||||
int pre_j;
|
||||
int prev_index;
|
||||
int downsample; /* min 4, max 256 */
|
||||
int output_scale;
|
||||
int squelch_level;
|
||||
int signal[2048]; /* 16 bit signed i/q pairs */
|
||||
int16_t signal2[2048]; /* signal has lowpass, signal2 has demod */
|
||||
int signal_len;
|
||||
FILE *file;
|
||||
int now_r;
|
||||
int now_j;
|
||||
int pre_r;
|
||||
int pre_j;
|
||||
int prev_index;
|
||||
int downsample; /* min 4, max 256 */
|
||||
int output_scale;
|
||||
int squelch_level;
|
||||
int signal[2048]; /* 16 bit signed i/q pairs */
|
||||
int16_t signal2[2048]; /* signal has lowpass, signal2 has demod */
|
||||
int signal_len;
|
||||
FILE *file;
|
||||
int edge;
|
||||
uint32_t freqs[32];
|
||||
int freq_len;
|
||||
int freq_now;
|
||||
uint32_t sample_rate;
|
||||
};
|
||||
|
||||
void usage(void)
|
||||
@ -79,6 +85,7 @@ void usage(void)
|
||||
fprintf(stderr,
|
||||
"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"
|
||||
"\t (use multiple -f for scanning !!BROKEN!!)\n"
|
||||
"\t[-s samplerate (default: 24000 Hz)]\n"
|
||||
"\t[-d device_index (default: 0)]\n"
|
||||
"\t[-g tuner_gain (default: -1dB)]\n"
|
||||
@ -203,7 +210,8 @@ int mad(int *samples, int len, int 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;
|
||||
/* 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_j = mad(&(fm->signal[1]), len, 2);
|
||||
if ((dev_r > sq_l) || (dev_j > sq_l)) {
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
/* weak signal, kill it entirely */
|
||||
for (i=0; i<len; i++) {
|
||||
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)
|
||||
{
|
||||
struct fm_state *fm2;
|
||||
int sr, freq_next;
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
@ -230,34 +269,18 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
|
||||
rotate_90(buf, len);
|
||||
low_pass(fm2, buf, len);
|
||||
fm_demod(fm2);
|
||||
post_squelch(fm2);
|
||||
sr = post_squelch(fm2);
|
||||
/* ignore under runs for now */
|
||||
fwrite(fm2->signal2, 2, fm2->signal_len/2, fm2->file);
|
||||
}
|
||||
|
||||
static void optimal_settings(struct fm_state *fm, int freq, int rate, int edge)
|
||||
{
|
||||
int r, capture_freq, capture_rate;
|
||||
fm->downsample = (1000000 / rate) + 1;
|
||||
fprintf(stderr, "Oversampling by: %ix.\n", fm->downsample);
|
||||
capture_rate = fm->downsample * rate;
|
||||
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;
|
||||
if (fm2->freq_len > 1 && !sr) {
|
||||
freq_next = (fm2->freq_now + 1) % fm2->freq_len;
|
||||
optimal_settings(fm2, freq_next, 1);
|
||||
rtlsdr_reset_buffer(dev);
|
||||
//rtlsdr_read_async(dev, rtlsdr_callback, ctx,
|
||||
// DEFAULT_ASYNC_BUF_NUMBER, DEFAULT_BUF_LENGTH);
|
||||
//rtlsdr_wait_async(dev, rtlsdr_callback, (void *)0);
|
||||
//rtlsdr_wait_async(dev, rtlsdr_callback, ctx);
|
||||
}
|
||||
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)
|
||||
@ -269,15 +292,16 @@ int main(int argc, char **argv)
|
||||
char *filename = NULL;
|
||||
int n_read;
|
||||
int r, opt;
|
||||
int i, edge = 0, gain = -10; // tenths of a dB
|
||||
int i, gain = -10; // tenths of a dB
|
||||
uint8_t *buffer;
|
||||
uint32_t dev_index = 0;
|
||||
uint32_t frequency = 100000000;
|
||||
uint32_t samp_rate = DEFAULT_SAMPLE_RATE;
|
||||
uint32_t out_block_size = DEFAULT_BUF_LENGTH;
|
||||
int device_count;
|
||||
char vendor[256], product[256], serial[256];
|
||||
fm.freqs[0] = 100000000;
|
||||
fm.sample_rate = DEFAULT_SAMPLE_RATE;
|
||||
fm.squelch_level = 150;
|
||||
fm.freq_len = 0;
|
||||
#ifndef _WIN32
|
||||
while ((opt = getopt(argc, argv, "d:f:g:s:b:l:E::")) != -1) {
|
||||
switch (opt) {
|
||||
@ -285,7 +309,8 @@ int main(int argc, char **argv)
|
||||
dev_index = atoi(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
frequency = (uint32_t)atof(optarg);
|
||||
fm.freqs[fm.freq_len] = (uint32_t)atof(optarg);
|
||||
fm.freq_len++;
|
||||
break;
|
||||
case 'g':
|
||||
gain = (int)(atof(optarg) * 10);
|
||||
@ -294,10 +319,10 @@ int main(int argc, char **argv)
|
||||
fm.squelch_level = (int)atof(optarg);
|
||||
break;
|
||||
case 's':
|
||||
samp_rate = (uint32_t)atof(optarg);
|
||||
fm.sample_rate = (uint32_t)atof(optarg);
|
||||
break;
|
||||
case 'E':
|
||||
edge = 1;
|
||||
fm.edge = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
@ -316,7 +341,8 @@ int main(int argc, char **argv)
|
||||
dev_index = atoi(argv[1]);
|
||||
samp_rate = atoi(argv[2])*1000;
|
||||
gain=(int)(atof(argv[3]) * 10);
|
||||
frequency = atoi(argv[4]);
|
||||
fm.freqs[0] = atoi(argv[4]);
|
||||
fm.freq_len = 1;
|
||||
filename = argv[5];
|
||||
#endif
|
||||
out_block_size = DEFAULT_BUF_LENGTH;
|
||||
@ -356,7 +382,7 @@ int main(int argc, char **argv)
|
||||
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
|
||||
#endif
|
||||
|
||||
optimal_settings(&fm, frequency, samp_rate, edge);
|
||||
optimal_settings(&fm, 0, 0);
|
||||
|
||||
/* Set the tuner gain */
|
||||
r = rtlsdr_set_tuner_gain(dev, gain);
|
||||
|
Loading…
Reference in New Issue
Block a user