Procházet zdrojové kódy

rtl_fm: set nearest gain

Signed-off-by: Steve Markgraf <steve@steve-m.de>
Kyle Keen před 11 roky
rodič
revize
b70720b9b6
1 změnil soubory, kde provedl 48 přidání a 12 odebrání
  1. 48 12
      src/rtl_fm.c

+ 48 - 12
src/rtl_fm.c

@@ -32,13 +32,15 @@
  *       scale squelch to other input parameters
  *       test all the demodulations
  *       pad output on hop
- *       nearest gain approx
  *       frequency ranges could be stored better
  *       scaled AM demod amplification
  *       auto-hop after time limit
  *       peak detector to tune onto stronger signals
  *       use slower sample rates (250k) for nbfm
  *       offset tuning
+ *       fifo for active hop frequency
+ *       clips
+ *       real squelch math
  */
 
 #include <errno.h>
@@ -150,10 +152,16 @@ void usage(void)
 		"\t[-U enables USB mode (default: off)]\n"
 		//"\t[-D enables DSB mode (default: off)]\n"
 		"\t[-R enables raw mode (default: off, 2x16 bit output)]\n"
-		"\t[-F enables high quality FIR (default: off/square)]\n"
+		"\t[-F enables Hamming FIR (default: off/square)]\n"
 		"\t[-D enables de-emphasis (default: off)]\n"
 		"\t[-C enables DC blocking of output (default: off)]\n"
-		"\t[-A std/fast/lut choose atan math (default: std)]\n\n"
+		"\t[-A std/fast/lut choose atan math (default: std)]\n"
+		//"\t[-C clip_path (default: off)\n"
+		//"\t (create time stamped raw clips, requires squelch)\n"
+		//"\t (path must have '\%s' and will expand to date_time_freq)\n"
+		//"\t[-H hop_fifo (default: off)\n"
+		//"\t (fifo will contain the active frequency)\n"
+		"\n"
 		"Produces signed 16 bit ints, use Sox or aplay to hear them.\n"
 		"\trtl_fm ... - | play -t raw -r 24k -es -b 16 -c 1 -V1 -\n"
 		"\t             | aplay -r 24k -f S16_LE -t raw -c 1\n"
@@ -230,17 +238,18 @@ void low_pass(struct fm_state *fm, unsigned char *buf, uint32_t len)
 }
 
 void build_fir(struct fm_state *fm)
-/* for now, a simple triangle 
- * fancy FIRs are equally expensive, so use one */
+/* hamming */
 /* point = sum(sample[i] * fir[i] * fir_len / fir_sum) */
 {
+	double a, b, w, N1;
 	int i, len;
 	len = fm->downsample;
-	for(i = 0; i < (len/2); i++) {
-		fm->fir[i] = i;
-	}
-	for(i = len-1; i >= (len/2); i--) {
-		fm->fir[i] = len - i;
+	a = 25.0/46.0;
+	b = 21.0/46.0;
+	N1 = (double)(len-1);
+	for(i = 0; i < len; i++) {
+		w = a - b*cos(2*i*M_PI/N1);
+		fm->fir[i] = (int)(w * 255);
 	}
 	fm->fir_sum = 0;
 	for(i = 0; i < len; i++) {
@@ -255,13 +264,17 @@ void low_pass_fir(struct fm_state *fm, unsigned char *buf, uint32_t len)
 	int i=0, i2=0, i3=0;
 	while (i < (int)len) {
 		i3 = fm->prev_index;
-		fm->now_r += ((int)buf[i]   - 127) * fm->fir[i3] * fm->downsample / fm->fir_sum;
-		fm->now_j += ((int)buf[i+1] - 127) * fm->fir[i3] * fm->downsample / fm->fir_sum;
+		fm->now_r += ((int)buf[i]   - 127) * fm->fir[i3];
+		fm->now_j += ((int)buf[i+1] - 127) * fm->fir[i3];
 		i += 2;
 		fm->prev_index++;
 		if (fm->prev_index < fm->downsample) {
 			continue;
 		}
+		fm->now_r *= fm->downsample;
+		fm->now_j *= fm->downsample;
+		fm->now_r /= fm->fir_sum;
+		fm->now_j /= fm->fir_sum;
 		fm->signal[i2]   = fm->now_r; //* fm->output_scale;
 		fm->signal[i2+1] = fm->now_j; //* fm->output_scale;
 		fm->prev_index = 0;
@@ -730,6 +743,28 @@ void frequency_range(struct fm_state *fm, char *arg)
 	step[-1] = ':';
 }
 
+int nearest_gain(int target_gain)
+{
+	int i, err1, err2, count, close_gain;
+	int* gains;
+	count = rtlsdr_get_tuner_gains(dev, NULL);
+	if (count <= 0) {
+		return 0;
+	}
+	gains = malloc(sizeof(int) * count);
+	count = rtlsdr_get_tuner_gains(dev, gains);
+	close_gain = gains[0];
+	for (i=0; i<count; i++) {
+		err1 = abs(target_gain - close_gain);
+		err2 = abs(target_gain - gains[i]);
+		if (err2 < err1) {
+			close_gain = gains[i];
+		}
+	}
+	free(gains);
+	return close_gain;
+}
+
 void fm_init(struct fm_state *fm)
 {
 	fm->freqs[0] = 100000000;
@@ -952,6 +987,7 @@ int main(int argc, char **argv)
 		r = rtlsdr_set_tuner_gain_mode(dev, 0);
 	} else {
 		r = rtlsdr_set_tuner_gain_mode(dev, 1);
+		gain = nearest_gain(gain);
 		r = rtlsdr_set_tuner_gain(dev, gain);
 	}
 	if (r != 0) {