mirror of
				https://github.com/rtlsdrblog/rtl-sdr-blog.git
				synced 2025-10-31 08:58:09 +01:00 
			
		
		
		
	rtl_fm: broken multi freq scanning
Signed-off-by: Steve Markgraf <steve@steve-m.de>
This commit is contained in:
		
				
					committed by
					
						 Steve Markgraf
						Steve Markgraf
					
				
			
			
				
	
			
			
			
						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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user