how/where to merge code: patch files

Hayati Ayguen h_ayguen at web.de
Sat Jul 18 15:12:24 UTC 2015


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



More information about the osmocom-sdr mailing list