rtl_fm: set nearest gain

Signed-off-by: Steve Markgraf <steve@steve-m.de>
This commit is contained in:
Kyle Keen 2013-09-07 18:26:10 -04:00 committed by Steve Markgraf
parent 31cef2ef55
commit b70720b9b6

View File

@ -32,13 +32,15 @@
* scale squelch to other input parameters * scale squelch to other input parameters
* test all the demodulations * test all the demodulations
* pad output on hop * pad output on hop
* nearest gain approx
* frequency ranges could be stored better * frequency ranges could be stored better
* scaled AM demod amplification * scaled AM demod amplification
* auto-hop after time limit * auto-hop after time limit
* peak detector to tune onto stronger signals * peak detector to tune onto stronger signals
* use slower sample rates (250k) for nbfm * use slower sample rates (250k) for nbfm
* offset tuning * offset tuning
* fifo for active hop frequency
* clips
* real squelch math
*/ */
#include <errno.h> #include <errno.h>
@ -150,10 +152,16 @@ void usage(void)
"\t[-U enables USB mode (default: off)]\n" "\t[-U enables USB mode (default: off)]\n"
//"\t[-D enables DSB mode (default: off)]\n" //"\t[-D enables DSB mode (default: off)]\n"
"\t[-R enables raw mode (default: off, 2x16 bit output)]\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[-D enables de-emphasis (default: off)]\n"
"\t[-C enables DC blocking of output (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" "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" "\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" "\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) void build_fir(struct fm_state *fm)
/* for now, a simple triangle /* hamming */
* fancy FIRs are equally expensive, so use one */
/* point = sum(sample[i] * fir[i] * fir_len / fir_sum) */ /* point = sum(sample[i] * fir[i] * fir_len / fir_sum) */
{ {
double a, b, w, N1;
int i, len; int i, len;
len = fm->downsample; len = fm->downsample;
for(i = 0; i < (len/2); i++) { a = 25.0/46.0;
fm->fir[i] = i; b = 21.0/46.0;
} N1 = (double)(len-1);
for(i = len-1; i >= (len/2); i--) { for(i = 0; i < len; i++) {
fm->fir[i] = len - i; w = a - b*cos(2*i*M_PI/N1);
fm->fir[i] = (int)(w * 255);
} }
fm->fir_sum = 0; fm->fir_sum = 0;
for(i = 0; i < len; i++) { 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; int i=0, i2=0, i3=0;
while (i < (int)len) { while (i < (int)len) {
i3 = fm->prev_index; i3 = fm->prev_index;
fm->now_r += ((int)buf[i] - 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] * fm->downsample / fm->fir_sum; fm->now_j += ((int)buf[i+1] - 127) * fm->fir[i3];
i += 2; i += 2;
fm->prev_index++; fm->prev_index++;
if (fm->prev_index < fm->downsample) { if (fm->prev_index < fm->downsample) {
continue; 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] = fm->now_r; //* fm->output_scale;
fm->signal[i2+1] = fm->now_j; //* fm->output_scale; fm->signal[i2+1] = fm->now_j; //* fm->output_scale;
fm->prev_index = 0; fm->prev_index = 0;
@ -730,6 +743,28 @@ void frequency_range(struct fm_state *fm, char *arg)
step[-1] = ':'; 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) void fm_init(struct fm_state *fm)
{ {
fm->freqs[0] = 100000000; fm->freqs[0] = 100000000;
@ -952,6 +987,7 @@ int main(int argc, char **argv)
r = rtlsdr_set_tuner_gain_mode(dev, 0); r = rtlsdr_set_tuner_gain_mode(dev, 0);
} else { } else {
r = rtlsdr_set_tuner_gain_mode(dev, 1); r = rtlsdr_set_tuner_gain_mode(dev, 1);
gain = nearest_gain(gain);
r = rtlsdr_set_tuner_gain(dev, gain); r = rtlsdr_set_tuner_gain(dev, gain);
} }
if (r != 0) { if (r != 0) {