This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/osmocom-sdr@lists.osmocom.org/.
Hayati Ayguen h_ayguen at web.de
Hi Osmocom guys,
please consider merging the 2 attached patches.
The first patch:
added option -L to print current level values
added option -c to configure de-emphasis time constant for wbfm
added option -v to print verbose (debug) output
added alias modulation names nbfm, nfm, wfm
now the options in detail:
option -L:
"rtl_fm -L 10 -M fm": prints current level to stderr, every 10th
calculation. This allows monitoring of the noise (or signal) level, to
help setting an optimal squelch threshold.
option -c:
"rtl_fm -M wbfm -c 50" uses de-emphasis time constant for europe.
One might also write "-c us" to use the north american 75 microSec standard.
"-c eu" will use the european 50 microSec standard.
option -v:
"rtl_fm -v 1 -f 99.3M" displays verbose debug information on calculation
of frequency, so that user might understand how/what frequency is tuned to.
modulation names:
found myself writing "wfm" instead of "wbfm". now the aliases are also
accepted.
The second patch:
added dc filter on raw data (after decimation) with option "-E rdc"
added option "-q" for setting averaging speed for "rdc"
added option "-E adc" in addition to "-E dc"
Please have a look in my previous mail with subject
"rtl_fm: degraded demodulation caused by self-introduced DC !?"
to understand the reason for a second dc filter.
kind regards,
Hayati
Am 18.07.2015 um 16:26 schrieb Marcus Müller:
> Hi Hayati,
>
> I'm pretty sure git.osmocom.org is the upstream; to ask steve-m to merge
> your changes into his repository, just log on to github, go to
> https://github.com/hayguen/librtlsdr, and you should see something like
> "This branch is 2 commits ahead of steve-m:master Pull Request"
> right at the top, just under the header where you can select your branch.
>
> The Impressum of osmocom.org said to send in patches via this mailing
> list, so that's what I did once, and that worked too :), so assuming
> steve-m's repo is called "steve-m" in your git ("git remote -v" will
> tell), and the modified master branch being currently checked out
>
> git format-patch steve-m/master
>
> will generate a patch file for each commit between your master's HEAD
> and steve-m/master.
>
> Greetings,
> Marcus
>
>
> On 18.07.2015 16:06, Hayati Ayguen wrote:
>> Hi,
>>
>> just wanted to ask, what to do, so that my changes on
>> https://github.com/hayguen/librtlsdr get merged into
>> https://github.com/steve-m/librtlsdr ?
>>
>> Just now, in this moment, i realize, that there's alos
>> git://git.osmocom.org/rtl-sdr.git referenced at
>> http://sdr.osmocom.org/trac/wiki/rtl-sdr
>>
>> Ok, which is the real origin for rtl-sdr?
>> What is needed to get the changes there?
>>
>>
>> Besides the changes on rtl_fm i've developed a small tool, i called
>> "stdin2wav". It's used by piping rtl_fm's output into stdin2wav, which
>> then saves the output into wave files using libsndfile.
>> Besides saving, it can be combined with the squelch function of rtl_fm.
>> stdin2wav closes the wave file when no more data comes from stdin .. and
>> re-opens a new wave file when new data arrives, cause the squelch
>> opened ..
>>
>> Can/should this small tool also merged to rtl-sdr? Someone has a better
>> place?
>> By the way: someone has a better name?
>>
>>
>> kind regards,
>> Hayati
>>
>
-------------- next part --------------
From 4a0e25ba41fc81f29ddd84aa5dbf2bbc1358dbbb Mon Sep 17 00:00:00 2001
From: Hayati Ayguen <h_ayguen at web.de>
Date: Sun, 14 Jun 2015 02:17:40 +0200
Subject: [PATCH 1/2] added option -L to print current level values added
option -c to configure de-emphasis time constant for wbfm added option -v to
print verbose (debug) output added alias modulation names nbfm, nfm, wfm
---
src/rtl_fm.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 74 insertions(+), 8 deletions(-)
diff --git a/src/rtl_fm.c b/src/rtl_fm.c
index 0f7ac38..8cf95f0 100644
--- a/src/rtl_fm.c
+++ b/src/rtl_fm.c
@@ -4,6 +4,7 @@
* Copyright (C) 2012 by Hoernchen <la at tfc-server.de>
* Copyright (C) 2012 by Kyle Keen <keenerd at gmail.com>
* Copyright (C) 2013 by Elias Oenal <EliasOenal at gmail.com>
+ * Copyright (C) 2015 by Hayati Ayguen <h_ayguen at web.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -92,6 +93,13 @@ static int *atan_lut = NULL;
static int atan_lut_size = 131072; /* 512 KB */
static int atan_lut_coef = 8;
+static int verbosity = 0;
+static int printLevels = 0;
+static int printLevelNo = 1;
+static int levelMax = 0;
+static int levelMaxMax = 0;
+static double levelSum = 0.0;
+
struct dongle_state
{
int exit_flag;
@@ -187,16 +195,21 @@ void usage(void)
"\t-f frequency_to_tune_to [Hz]\n"
"\t use multiple -f for scanning (requires squelch)\n"
"\t ranges supported, -f 118M:137M:25k\n"
+ "\t[-v verbosity (default: 0)]\n"
"\t[-M modulation (default: fm)]\n"
- "\t fm, wbfm, raw, am, usb, lsb\n"
+ "\t fm or nbfm or nfm, wbfm or wfm, raw or iq, am, usb, lsb\n"
"\t wbfm == -M fm -s 170k -o 4 -A fast -r 32k -l 0 -E deemp\n"
"\t raw mode outputs 2x16 bit IQ pairs\n"
"\t[-s sample_rate (default: 24k)]\n"
"\t[-d device_index (default: 0)]\n"
"\t[-g tuner_gain (default: automatic)]\n"
"\t[-l squelch_level (default: 0/off)]\n"
+ "\t[-L N prints levels every N calculations]\n"
+ "\t output are comma separated values (csv):\n"
+ "\t mean since last output, max since last output, overall max, squelch\n"
+ "\t[-c de-emphasis_time_constant in us for wbfm. 'us' or 'eu' for 75/50 us (default: us)]\n"
//"\t for fm squelch is inverted\n"
- //"\t[-o oversampling (default: 1, 4 recommended)]\n"
+ "\t[-o oversampling (default: 1, 4 recommended)]\n"
"\t[-p ppm_error (default: 0)]\n"
"\t[-E enable_option (default: none)]\n"
"\t use multiple -E to enable multiple options\n"
@@ -759,6 +772,24 @@ void full_demod(struct demod_state *d)
} else {
d->squelch_hits = 0;}
}
+
+ if (printLevels) {
+ if (!sr)
+ sr = rms(d->lowpassed, d->lp_len, 1);
+ --printLevelNo;
+ if (printLevels) {
+ levelSum += sr;
+ if (levelMax < sr) levelMax = sr;
+ if (levelMaxMax < sr) levelMaxMax = sr;
+ if (!printLevelNo) {
+ printLevelNo = printLevels;
+ fprintf(stderr, "%f, %d, %d, %d\n", (levelSum / printLevels), levelMax, levelMaxMax, d->squelch_level );
+ levelMax = 0;
+ levelSum = 0;
+ }
+ }
+ }
+
d->mode_demod(d); /* lowpassed -> result */
if (d->mode_demod == &raw_demod) {
return;
@@ -864,9 +895,16 @@ static void optimal_settings(int freq, int rate)
}
capture_freq = freq;
capture_rate = dm->downsample * dm->rate_in;
+ if (verbosity)
+ fprintf(stderr, "capture_rate = dm->downsample * dm->rate_in = %d * %d = %d\n", dm->downsample, dm->rate_in, capture_rate );
if (!d->offset_tuning) {
- capture_freq = freq + capture_rate/4;}
+ capture_freq = freq + capture_rate/4;
+ if (verbosity)
+ fprintf(stderr, "optimal_settings(freq = %d): capture_freq = freq + capture_rate/4 = %d\n", freq, capture_freq );
+ }
capture_freq += cs->edge * dm->rate_in / 2;
+ if (verbosity)
+ fprintf(stderr, "optimal_settings(freq = %d): capture_freq += cs->edge * dm->rate_in / 2 = %d * %d / 2 = %d\n", freq, cs->edge, dm->rate_in, capture_freq );
dm->output_scale = (1<<15) / (128 * dm->downsample);
if (dm->output_scale < 1) {
dm->output_scale = 1;}
@@ -874,6 +912,8 @@ static void optimal_settings(int freq, int rate)
dm->output_scale = 1;}
d->freq = (uint32_t)capture_freq;
d->rate = (uint32_t)capture_rate;
+ if (verbosity)
+ fprintf(stderr, "optimal_settings(freq = %d) delivers freq %.0f, rate %.0f\n", freq, (double)d->freq, (double)d->rate );
}
static void *controller_thread_fn(void *arg)
@@ -884,6 +924,8 @@ static void *controller_thread_fn(void *arg)
struct controller_state *s = arg;
if (s->wb_mode) {
+ if (verbosity)
+ fprintf(stderr, "wbfm: adding 16000 Hz to every intput frequency\n");
for (i=0; i < s->freq_len; i++) {
s->freqs[i] += 16000;}
}
@@ -896,6 +938,10 @@ static void *controller_thread_fn(void *arg)
verbose_offset_tuning(dongle.dev);}
/* Set the frequency */
+ if (verbosity) {
+ fprintf(stderr, "verbose_set_frequency(%.0f Hz)\n", (double)dongle.freq);
+ fprintf(stderr, " frequency is away from parametrized one, to avoid negative impact from dc\n");
+ }
verbose_set_frequency(dongle.dev, dongle.freq);
fprintf(stderr, "Oversampling input by: %ix.\n", demod.downsample);
fprintf(stderr, "Oversampling output by: %ix.\n", demod.post_downsample);
@@ -903,6 +949,8 @@ static void *controller_thread_fn(void *arg)
1000 * 0.5 * (float)ACTUAL_BUF_LENGTH / (float)dongle.rate);
/* Set the sample rate */
+ if (verbosity)
+ fprintf(stderr, "verbose_set_sample_rate(%.0f Hz)\n", (double)dongle.rate);
verbose_set_sample_rate(dongle.dev, dongle.rate);
fprintf(stderr, "Output at %u Hz.\n", demod.rate_in/demod.post_downsample);
@@ -1042,12 +1090,13 @@ int main(int argc, char **argv)
int r, opt;
int dev_given = 0;
int custom_ppm = 0;
+ int timeConstant = 75; /* default: U.S. 75 uS */
dongle_init(&dongle);
demod_init(&demod);
output_init(&output);
controller_init(&controller);
- while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:E:F:A:M:h")) != -1) {
+ while ((opt = getopt(argc, argv, "d:f:g:s:b:l:L:o:t:r:p:E:F:A:M:c:v:h")) != -1) {
switch (opt) {
case 'd':
dongle.dev_index = verbose_device_search(optarg);
@@ -1070,6 +1119,9 @@ int main(int argc, char **argv)
case 'l':
demod.squelch_level = (int)atof(optarg);
break;
+ case 'L':
+ printLevels = (int)atof(optarg);
+ break;
case 's':
demod.rate_in = (uint32_t)atofs(optarg);
demod.rate_out = (uint32_t)atofs(optarg);
@@ -1121,9 +1173,9 @@ int main(int argc, char **argv)
demod.custom_atan = 2;}
break;
case 'M':
- if (strcmp("fm", optarg) == 0) {
+ if (strcmp("nbfm", optarg) == 0 || strcmp("nfm", optarg) == 0 || strcmp("fm", optarg) == 0) {
demod.mode_demod = &fm_demod;}
- if (strcmp("raw", optarg) == 0) {
+ if (strcmp("raw", optarg) == 0 || strcmp("iq", optarg) == 0) {
demod.mode_demod = &raw_demod;}
if (strcmp("am", optarg) == 0) {
demod.mode_demod = &am_demod;}
@@ -1131,7 +1183,7 @@ int main(int argc, char **argv)
demod.mode_demod = &usb_demod;}
if (strcmp("lsb", optarg) == 0) {
demod.mode_demod = &lsb_demod;}
- if (strcmp("wbfm", optarg) == 0) {
+ if (strcmp("wbfm", optarg) == 0 || strcmp("wfm", optarg) == 0) {
controller.wb_mode = 1;
demod.mode_demod = &fm_demod;
demod.rate_in = 170000;
@@ -1142,6 +1194,17 @@ int main(int argc, char **argv)
demod.deemph = 1;
demod.squelch_level = 0;}
break;
+ case 'c':
+ if (strcmp("us", optarg) == 0)
+ timeConstant = 75;
+ else if (strcmp("eu", optarg) == 0)
+ timeConstant = 50;
+ else
+ timeConstant = (int)atof(optarg);
+ break;
+ case 'v':
+ verbosity = (int)atof(optarg);
+ break;
case 'h':
default:
usage();
@@ -1194,7 +1257,10 @@ int main(int argc, char **argv)
#endif
if (demod.deemph) {
- demod.deemph_a = (int)round(1.0/((1.0-exp(-1.0/(demod.rate_out * 75e-6)))));
+ double tc = (double)timeConstant * 1e-6;
+ demod.deemph_a = (int)round(1.0/((1.0-exp(-1.0/(demod.rate_out * tc)))));
+ if (verbosity)
+ fprintf(stderr, "using wbfm deemphasis filter with time constant %d us\n", timeConstant );
}
/* Set the tuner gain */
--
1.9.5.msysgit.1
-------------- next part --------------
From f5c7ad917134cdf7961ad801685d120521ab1d3d Mon Sep 17 00:00:00 2001
From: Hayati Ayguen <h_ayguen at web.de>
Date: Sat, 18 Jul 2015 15:40:33 +0200
Subject: [PATCH 2/2] added dc filter on raw data (after decimation) with
option "-E rdc" added option "-q" for setting averaging speed added
option "-E adc" in addition to "-E dc"
---
src/rtl_fm.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 51 insertions(+), 11 deletions(-)
diff --git a/src/rtl_fm.c b/src/rtl_fm.c
index 8cf95f0..f607e4e 100644
--- a/src/rtl_fm.c
+++ b/src/rtl_fm.c
@@ -146,7 +146,8 @@ struct demod_state
int deemph, deemph_a;
int now_lpr;
int prev_lpr_index;
- int dc_block, dc_avg;
+ int dc_block_audio, dc_avg, adc_block_const;
+ int dc_block_raw, dc_avgI, dc_avgQ, rdc_block_const;
void (*mode_demod)(struct demod_state*);
pthread_rwlock_t rw;
pthread_cond_t ready;
@@ -214,10 +215,13 @@ void usage(void)
"\t[-E enable_option (default: none)]\n"
"\t use multiple -E to enable multiple options\n"
"\t edge: enable lower edge tuning\n"
- "\t dc: enable dc blocking filter\n"
+ "\t rdc: enable dc blocking filter on raw I/Q data\n"
+ "\t adc: enable dc blocking filter on demodulated audio\n"
+ "\t dc: same as adc\n"
"\t deemp: enable de-emphasis filter\n"
"\t direct: enable direct sampling\n"
"\t offset: enable offset tuning\n"
+ "\t[-q dc_avg_factor for option rdc (default: 9)]\n"
"\tfilename ('-' means stdout)\n"
"\t omitting the filename also uses stdout\n\n"
"Experimental options:\n"
@@ -623,7 +627,7 @@ void deemph_filter(struct demod_state *fm)
}
}
-void dc_block_filter(struct demod_state *fm)
+void dc_block_audio_filter(struct demod_state *fm)
{
int i, avg;
int64_t sum = 0;
@@ -631,13 +635,37 @@ void dc_block_filter(struct demod_state *fm)
sum += fm->result[i];
}
avg = sum / fm->result_len;
- avg = (avg + fm->dc_avg * 9) / 10;
+ avg = (avg + fm->dc_avg * fm->adc_block_const) / ( fm->adc_block_const + 1 );
for (i=0; i < fm->result_len; i++) {
fm->result[i] -= avg;
}
fm->dc_avg = avg;
}
+void dc_block_raw_filter(struct demod_state *fm)
+{
+ /* derived from dc_block_audio_filter,
+ running over the raw I/Q components
+ */
+ int16_t *lp = fm->lowpassed;
+ int i, avgI, avgQ;
+ int64_t sumI = 0;
+ int64_t sumQ = 0;
+ for (i = 0; i < fm->lp_len; i += 2) {
+ sumI += lp[i];
+ sumQ += lp[i+1];
+ }
+ avgI = sumI / ( fm->lp_len / 2 );
+ avgQ = sumQ / ( fm->lp_len / 2 );
+ avgI = (avgI + fm->dc_avgI * fm->rdc_block_const) / ( fm->rdc_block_const + 1 );
+ avgQ = (avgQ + fm->dc_avgQ * fm->rdc_block_const) / ( fm->rdc_block_const + 1 );
+ for (i = 0; i < fm->lp_len; i += 2) {
+ lp[i] -= avgI;
+ lp[i+1] -= avgQ;
+ }
+ fm->dc_avgI = avgI;
+ fm->dc_avgQ = avgQ;
+}
int mad(int16_t *samples, int len, int step)
/* mean average deviation */
{
@@ -789,7 +817,9 @@ void full_demod(struct demod_state *d)
}
}
}
-
+ if (d->dc_block_raw) {
+ dc_block_raw_filter(d);
+ }
d->mode_demod(d); /* lowpassed -> result */
if (d->mode_demod == &raw_demod) {
return;
@@ -800,8 +830,8 @@ void full_demod(struct demod_state *d)
d->result_len = low_pass_simple(d->result, d->result_len, d->post_downsample);}
if (d->deemph) {
deemph_filter(d);}
- if (d->dc_block) {
- dc_block_filter(d);}
+ if (d->dc_block_audio) {
+ dc_block_audio_filter(d);}
if (d->rate_out2 > 0) {
low_pass_real(d);
//arbitrary_resample(d->result, d->result, d->result_len, d->result_len * d->rate_out2 / d->rate_out);
@@ -1017,8 +1047,13 @@ void demod_init(struct demod_state *s)
s->prev_lpr_index = 0;
s->deemph_a = 0;
s->now_lpr = 0;
- s->dc_block = 0;
+ s->dc_block_audio = 0;
s->dc_avg = 0;
+ s->adc_block_const = 9;
+ s->dc_block_raw = 0;
+ s->dc_avgI = 0;
+ s->dc_avgQ = 0;
+ s->rdc_block_const = 9;
pthread_rwlock_init(&s->rw, NULL);
pthread_cond_init(&s->ready, NULL);
pthread_mutex_init(&s->ready_m, NULL);
@@ -1096,7 +1131,7 @@ int main(int argc, char **argv)
output_init(&output);
controller_init(&controller);
- while ((opt = getopt(argc, argv, "d:f:g:s:b:l:L:o:t:r:p:E:F:A:M:c:v:h")) != -1) {
+ while ((opt = getopt(argc, argv, "d:f:g:s:b:l:L:o:t:r:p:E:q:F:A:M:c:v:h")) != -1) {
switch (opt) {
case 'd':
dongle.dev_index = verbose_device_search(optarg);
@@ -1150,8 +1185,10 @@ int main(int argc, char **argv)
case 'E':
if (strcmp("edge", optarg) == 0) {
controller.edge = 1;}
- if (strcmp("dc", optarg) == 0) {
- demod.dc_block = 1;}
+ if (strcmp("dc", optarg) == 0 || strcmp("adc", optarg) == 0) {
+ demod.dc_block_audio = 1;}
+ if (strcmp("rdc", optarg) == 0) {
+ demod.dc_block_raw = 1;}
if (strcmp("deemp", optarg) == 0) {
demod.deemph = 1;}
if (strcmp("direct", optarg) == 0) {
@@ -1159,6 +1196,9 @@ int main(int argc, char **argv)
if (strcmp("offset", optarg) == 0) {
dongle.offset_tuning = 1;}
break;
+ case 'q':
+ demod.rdc_block_const = atoi(optarg);
+ break;
case 'F':
demod.downsample_passes = 1; /* truthy placeholder */
demod.comp_fir_size = atoi(optarg);
--
1.9.5.msysgit.1