Hi All,
I would like to realize an algorithm to build the best possible dvb-t
sdr experience. The idea is, that no matter how many sdrs and what kind
of antenna you have,
the software gets the best out of your hardware.
This is what I have thought:
The user community of a system depends on how useful it is,
how easy it is to use, build and how much money it costs.
Rtl-sdrs are quite cheap, but for now a user has no benefit of having
multiple sdrs in its system.
That is why I'm searching a way to correlate the signals of the sdrs
without hardware modification. I think everyone of you has seen the noise from
the power source. Has anyone tried to build a filter to use that noise
to calculate the delay between multiple dongles?
I mean, they get the same noise. I don't know if it is sufficient,
but it is also a good spot, to put some artificial noise in, as it can be easily
accessed and does not interfere with rf circuitry when it is switched off.
Is that an useful approach?
Do you think this could work? Did I miss something?
regards,
Steve
Hello
We are doing a ADS-B reciever senior project,
Can we have the building blocks in the gnu radio for that?
Please help us
We are using the hackrf one hardware
Which is the osmocom source in the gnu radio
Thanks
Sent from my iPhone
Hello,
I recently purchased a NooElec nesdr mini dongle. I want to install it on
Linux Mint 17.1. I have rtl-sdr installed. I have blacklisted the
dvb_usb_rtl28xxu driver. When I run rtl_test it reports that the dongle is
present and sending. When I run rtl_sdr -t to check the tuning range it
reports no E4000 tuner found.
Called NooElec for tech support. Got link for linux install but got error
"page not found". Tried to get on their mailing list from their IE page. Bad
gateway error 502. Looks like support may be difficult to get through
NooElec.
Does this error indicate a defective rtl dongle? Where can I find the
install procedure for the NooElec R820T NESDR mini. All responses are
appreciated.
Thank you,
Marty, N3MOW
N3mow(a)arrl.net <mailto:N3mow@arrl.net> mmcg29440(a)frontier.net
<mailto:mmcg29440@frontier.net>
So since there are now three radios (that I know) that has a hardware
Bias T support (HackRF, RTLSDR, Airspy) I added a set_biast and
get_biast methods to the default Source API. I also added Airspy and
HackRF bindings to enable / disable Bias T. The RTLSDR isn't merged into
mainstream, so I didn't added anything.
There is also the default implementations (doing nothing for set, and
returning false for get), so no breaks on the current source or current
applications.
--
Lucas Teske
Teske Virtual System
GPG: 4A90 974B ACE0 A9A6 AF09 B3B1 6C39 C1C1 6A9D A7BE
I have a Panadapter program, written in python, that throws an error
"undefined symbol Set_Tuner_Bandwith in librtlsdr0" Searching the net I've
found that set_tuner_Baandwith may have been dropped from the library. I'm
using version 5.3. One web site said that it had been added back in the
latest revision v0.7.0. Tried loading the new library and now find that
RTL-SDR requires dependencies found in librtlsdr0 version 5.3. Is there a
work around to eliminate this error. I did download the latest rtl-sdr but
it will not compile because of the dependency problem
I did not write the program so I hesitate to take it apart and I have not
received much help from the author. BITW I'm not the greatest linux person
so I need clear answers. Having said that all responses will be appreciated.
73
Marty, N3MOW
I have been playing with the rtl_fm program and most of
it works amazingly well but I can not seem to get the squelch to
stay open when receiving signals.
I have not tried to analyze the source yet so I am asking
what principle drives this squelch?
In the analog world, the best squelches for FM receivers
tend to be noise-driven and use a high-pass filter to filter out
normal audio. When the noise drops below a preset threshold, the
squelch opens.
For AM receivers, a cheap and easy solution is to monitor
the AGC and open the squelch when there is AGC voltage above a
preset level.
What I am noticing is that if I set the l value to a
point just above where the noise stops, signals do open the
squelch but even strong signals will not keep it from flickering
on and off constantly.
If I set the l value any lower, the squelch is always
open so that is not the issue.
I have tried signals that are absolutely full-quieting,
with and without CTCSS and the squelch opens briefly, closes for
a fraction of a second, opens for another fraction of a second
and randomly flickers on and off for the whole transmission.
On rare occasions, the squelch opens when the signal
starts, stays open and then closes properly after the carrier
leaves.
Some of these signals are even ever so slightly noisy and I have
heard this situation with and without PL tones or CTCSS so that
doesn't seem to matter.
Finally, I thought it might have something to do with too
narrow a bandwidth so I increased the sampling rate to 24 K which
made no difference at all.
If the signal has voice on it, the flickering doesn't
seem to be effected by the words.
Basically, what is this squelch responding to to keep flapping?
Martin McCormick WB5AGZ
Hi,
has anyone yet tried to optimize the rtl drivers towards using less
energy on the chipset (cpu doesn't matter for my purpose). I just
noticed that the r820 tuner gets awful hot when used normally or even
when the device is just inserted into the usb port thus supplied with
power. I also have multiple E4000 Tuner based dongles, but these do seem
to heat up pretty well also. My hackrf stays quite cold compared to that.
Are there chipsets known for less power consumption (thus less heat)? I
doubt software could really do much about the chip design, but i'm not
deep enough into the rtl chipset to judge whether it's more of a
software- or hardware-issue.
Any ideas on that topic?
Thanks!!
Best regards, Ricardo
Hi list,
there is a bug in v2. I didn't put the gain array in the priv structure but used
a global variable so multiple instance would use the same variable.
v3 fix this by putting a gain[] in the priv structure so every dongle get its
array allocated with a malloc.
best regards
Luigi
Signed-off-by: Luigi Tarenga <luigi.tarenga(a)gmail.com>
---
include/rtl-sdr.h | 59 +++++++++++++++++++++++++
include/tuner_r82xx.h | 7 +++
src/librtlsdr.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++---
src/tuner_r82xx.c | 81 ++++++++++++++++++++++++++++++++++
4 files changed, 258 insertions(+), 7 deletions(-)
diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h
index fe64bea..3719df4 100644
--- a/include/rtl-sdr.h
+++ b/include/rtl-sdr.h
@@ -200,6 +200,65 @@ RTLSDR_API enum rtlsdr_tuner rtlsdr_get_tuner_type(rtlsdr_dev_t *dev);
RTLSDR_API int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains);
/*!
+ * Set the gain of a single gain stage for the device.
+ *
+ * Valid gain values may be queried with \ref rtlsdr_get_tuner_gain_stage_gains function.
+ * Usually those are from 0 to a positive integer plus -1 to set the stage in Auto gain mode.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param stage from 0 to number of gain stages minus 1.
+ * \param gain from 0 to maximum supported gain for selected stage or -1 to set Auto gain mode.
+ * \return 0 on success
+ */
+RTLSDR_API int rtlsdr_set_tuner_gain_stage(rtlsdr_dev_t *dev, int stage, int gain);
+
+
+/*!
+ * Get the gain of a single gain stage for the device.
+ *
+ * The value returned is a number from 0 to maximum supported gain. or -1 to indicate Auto gain mode.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param stage from 0 to number of gain stages minus 1.
+ * \return the gain value in a range from 0 to maximum supported gain or -1 if Auto gain mode.
+ */
+RTLSDR_API int rtlsdr_get_tuner_gain_stage(rtlsdr_dev_t *dev, int stage);
+
+
+/*!
+ * Get the number of gain stages supported by the device.
+ *
+ * The value returned is a number from 0 to the number of independent gain stages in the device.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \return the number of gain stages in the devices. 0 if none are supported.
+ */
+RTLSDR_API int rtlsdr_get_tuner_gain_stages(rtlsdr_dev_t *dev);
+
+/*!
+ * Get the supported values of gains in tenth of dB for a given stage.
+ *
+ * The value returned is the number of gain steps for the given stage and the maximum supported
+ * gain value plus one. The returned value -1 is the maximum value that
+ * can be used with \ref rtlsdr_set_tuner_gain_stage function as gain parameter.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param stage from 0 to number of gain stages minus 1.
+ * \param gains a pointer to an array of integer where supported dB steps will be copied. NULL for no copy.
+ * \return the number of gain steps for the given stage.
+ */
+RTLSDR_API int rtlsdr_get_tuner_gain_stage_gains(rtlsdr_dev_t *dev, int stage, int *gains);
+
+/*!
+ * Get the name of the given gain stage.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param stage from 0 to number of gain stages minus 1.
+ * \return the address of a NULL terminated char array containing a descriptive name of the give gain stage.
+ */
+RTLSDR_API const char* rtlsdr_get_tuner_gain_stage_name(rtlsdr_dev_t *dev, int stage);
+
+/*!
* Set the gain for the device.
* Manual gain mode must be enabled for this to work.
*
diff --git a/include/tuner_r82xx.h b/include/tuner_r82xx.h
index f6c206a..04bb113 100644
--- a/include/tuner_r82xx.h
+++ b/include/tuner_r82xx.h
@@ -38,6 +38,7 @@
#define NUM_REGS 30
#define NUM_IMR 5
#define IMR_TRIAL 9
+#define NUM_GAIN_STAGES 3
#define VER_NUM 49
@@ -90,6 +91,7 @@ struct r82xx_priv {
enum r82xx_tuner_type type;
uint32_t bw; /* in MHz */
+ int gain[NUM_GAIN_STAGES];
void *rtl_dev;
};
@@ -115,6 +117,11 @@ int r82xx_standby(struct r82xx_priv *priv);
int r82xx_init(struct r82xx_priv *priv);
int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq);
int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain);
+int r82xx_set_gain_stage(struct r82xx_priv *priv, int stage, int gain);
+int r82xx_get_gain_stage(struct r82xx_priv *priv, int stage);
+int r82xx_get_gain_stages(struct r82xx_priv *priv);
+int r82xx_get_gain_stage_gains(struct r82xx_priv *priv, int stage, int *gains);
+const char *r82xx_get_gain_stage_name(struct r82xx_priv *priv, int stage);
int r82xx_set_bandwidth(struct r82xx_priv *priv, int bandwidth, uint32_t rate);
#endif
diff --git a/src/librtlsdr.c b/src/librtlsdr.c
index 9b7ba52..d0db745 100644
--- a/src/librtlsdr.c
+++ b/src/librtlsdr.c
@@ -64,6 +64,11 @@ typedef struct rtlsdr_tuner_iface {
int (*set_gain)(void *, int gain /* tenth dB */);
int (*set_if_gain)(void *, int stage, int gain /* tenth dB */);
int (*set_gain_mode)(void *, int manual);
+ int (*set_gain_stage)(void *, int stage, int gain);
+ int (*get_gain_stage)(void *, int stage);
+ int (*get_gain_stages)(void *);
+ int (*get_gain_stage_gains)(void *, int stage, int *gains);
+ const char * (*get_gain_stage_name)(void *, int stage);
} rtlsdr_tuner_iface_t;
enum rtlsdr_async_status {
@@ -258,45 +263,76 @@ int r820t_set_gain(void *dev, int gain) {
rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
return r82xx_set_gain(&devt->r82xx_p, 1, gain);
}
+
int r820t_set_gain_mode(void *dev, int manual) {
rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
return r82xx_set_gain(&devt->r82xx_p, manual, 0);
}
+int r820t_set_gain_stage(void *dev, int stage, int gain) {
+ rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
+ return r82xx_set_gain_stage(&devt->r82xx_p, stage, gain);
+}
+
+int r820t_get_gain_stage(void *dev, int stage) {
+ rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
+ return r82xx_get_gain_stage(&devt->r82xx_p, stage);
+}
+
+int r820t_get_gain_stages(void *dev) {
+ rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
+ return r82xx_get_gain_stages(&devt->r82xx_p);
+}
+
+int r820t_get_gain_stage_gains(void *dev, int stage, int *gains) {
+ rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
+ return r82xx_get_gain_stage_gains(&devt->r82xx_p, stage, gains);
+}
+
+const char *r820t_get_gain_stage_name(void *dev, int stage) {
+ rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
+ return r82xx_get_gain_stage_name(&devt->r82xx_p, stage);
+}
+
/* definition order must match enum rtlsdr_tuner */
static rtlsdr_tuner_iface_t tuners[] = {
{
- NULL, NULL, NULL, NULL, NULL, NULL, NULL /* dummy for unknown tuners */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* dummy for unknown tuners */
},
{
e4000_init, e4000_exit,
e4000_set_freq, e4000_set_bw, e4000_set_gain, e4000_set_if_gain,
- e4000_set_gain_mode
+ e4000_set_gain_mode, NULL, NULL, NULL, NULL, NULL
},
{
_fc0012_init, fc0012_exit,
fc0012_set_freq, fc0012_set_bw, _fc0012_set_gain, NULL,
- fc0012_set_gain_mode
+ fc0012_set_gain_mode, NULL, NULL, NULL, NULL, NULL
},
{
_fc0013_init, fc0013_exit,
fc0013_set_freq, fc0013_set_bw, _fc0013_set_gain, NULL,
- fc0013_set_gain_mode
+ fc0013_set_gain_mode, NULL, NULL, NULL, NULL, NULL
},
{
fc2580_init, fc2580_exit,
_fc2580_set_freq, fc2580_set_bw, fc2580_set_gain, NULL,
- fc2580_set_gain_mode
+ fc2580_set_gain_mode, NULL, NULL, NULL, NULL, NULL
},
{
r820t_init, r820t_exit,
r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL,
- r820t_set_gain_mode
+ r820t_set_gain_mode,
+ r820t_set_gain_stage,
+ r820t_get_gain_stage,
+ r820t_get_gain_stages,
+ r820t_get_gain_stage_gains,
+ r820t_get_gain_stage_name
},
{
r820t_init, r820t_exit,
r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL,
- r820t_set_gain_mode
+ r820t_set_gain_mode, NULL, NULL, NULL, NULL, NULL
},
};
@@ -1089,6 +1125,74 @@ int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int mode)
return r;
}
+int rtlsdr_set_tuner_gain_stage(rtlsdr_dev_t *dev, int stage, int gain)
+{
+ int r = 0;
+
+ if (!dev || !dev->tuner)
+ return -1;
+
+ if (dev->tuner->set_gain_stage) {
+ rtlsdr_set_i2c_repeater(dev, 1);
+ r = dev->tuner->set_gain_stage(dev, stage, gain);
+ rtlsdr_set_i2c_repeater(dev, 0);
+ }
+
+ return r;
+}
+
+int rtlsdr_get_tuner_gain_stage(rtlsdr_dev_t *dev, int stage)
+{
+ int r = 0;
+
+ if (!dev || !dev->tuner)
+ return -1;
+
+ if (dev->tuner->get_gain_stage)
+ r = dev->tuner->get_gain_stage(dev, stage);
+
+ return r;
+}
+
+int rtlsdr_get_tuner_gain_stages(rtlsdr_dev_t *dev)
+{
+ int r = 0;
+
+ if (!dev || !dev->tuner)
+ return -1;
+
+ if (dev->tuner->get_gain_stages)
+ r = dev->tuner->get_gain_stages(dev);
+
+ return r;
+}
+
+int rtlsdr_get_tuner_gain_stage_gains(rtlsdr_dev_t *dev, int stage, int *gains)
+{
+ int r = 0;
+
+ if (!dev || !dev->tuner)
+ return -1;
+
+ if (dev->tuner->get_gain_stage_gains)
+ r = dev->tuner->get_gain_stage_gains(dev, stage, gains);
+
+ return r;
+}
+
+const char *rtlsdr_get_tuner_gain_stage_name(rtlsdr_dev_t *dev, int stage)
+{
+ const char *r = "";
+
+ if (!dev || !dev->tuner)
+ return "";
+
+ if (dev->tuner->get_gain_stage_name)
+ r = dev->tuner->get_gain_stage_name(dev, stage);
+
+ return r;
+}
+
int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate)
{
int r = 0;
diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c
index f620238..eeb646f 100644
--- a/src/tuner_r82xx.c
+++ b/src/tuner_r82xx.c
@@ -1073,6 +1073,87 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain)
return 0;
}
+typedef struct r82xx_gain_stage {
+ const char *name;
+ const int *steps;
+ const int num;
+} r82xx_gain_stage_t;
+
+
+static r82xx_gain_stage_t gain_stage[NUM_GAIN_STAGES] = {
+ { "LNA", (int []) { 0, 9, 13, 40, 38, 13, 31, 22, 26, 31, 26, 14, 19, 5, 35, 13 }, 16 },
+ { "MIX", (int []) { 0, 5, 10, 10, 19, 9, 10, 25, 17, 10, 8, 16, 13, 6, 3, -8 }, 16 },
+ { "VGA", (int []) { 0, 26, 26, 30, 42, 35, 24, 13, 14, 32, 36, 34, 35, 37, 35, 36 }, 16 }
+};
+
+static const int r82xx_gain_stage_register[NUM_GAIN_STAGES] = { 0x05, 0x07, 0x0c };
+static const int r82xx_gain_stage_mask[NUM_GAIN_STAGES] = { 0x0f, 0x0f, 0x0f };
+static const int r82xx_gain_stage_manual[NUM_GAIN_STAGES] = { 0x01, 0x00, 0x00 };
+static const int r82xx_gain_stage_manual_mask[NUM_GAIN_STAGES] = { 0x10, 0x10, 0x10 };
+
+int r82xx_set_gain_stage(struct r82xx_priv *priv, int stage, int gain)
+{
+ int rc;
+
+ if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage))
+ return -1;
+
+ if (gain < -1 || gain >= gain_stage[stage].num)
+ return -1;
+
+ if (gain >= 0) {
+ /* stage auto off */
+ rc = r82xx_write_reg_mask(priv, r82xx_gain_stage_register[stage], r82xx_gain_stage_manual[stage], r82xx_gain_stage_manual_mask[stage]);
+ if (rc < 0)
+ return rc;
+
+ rc = r82xx_write_reg_mask(priv, r82xx_gain_stage_register[stage], (uint8_t) gain, r82xx_gain_stage_mask[stage]);
+ if (rc < 0)
+ return rc;
+
+ priv->gain[stage] = gain;
+ } else {
+ /* stage auto on */
+ rc = r82xx_write_reg_mask(priv, r82xx_gain_stage_register[stage], ~(r82xx_gain_stage_manual[stage]), r82xx_gain_stage_manual_mask[stage]);
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
+}
+
+int r82xx_get_gain_stage(struct r82xx_priv *priv, int stage)
+{
+ if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage))
+ return 0;
+
+ return priv->gain[stage];
+}
+
+int r82xx_get_gain_stages(struct r82xx_priv *priv)
+{
+ return ARRAY_SIZE(gain_stage);
+}
+
+int r82xx_get_gain_stage_gains(struct r82xx_priv *priv, int stage, int *gains)
+{
+ if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage))
+ return -1;
+
+ if (gains)
+ memcpy(gains, gain_stage[stage].steps, gain_stage[stage].num * sizeof(int));
+
+ return gain_stage[stage].num;
+}
+
+const char *r82xx_get_gain_stage_name(struct r82xx_priv *priv, int stage)
+{
+ if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage))
+ return "";
+
+ return gain_stage[stage].name;
+}
+
/* Bandwidth contribution by low-pass filter. */
static const int r82xx_if_low_pass_bw_table[] = {
1700000, 1600000, 1550000, 1450000, 1200000, 900000, 700000, 550000, 450000, 350000
--
2.11.0
Hello list,
I repropose a patch to set independent gain for each stage with r820t tuner.
The approach should be enough generalized to be extended to e4000 tuner too.
I'm looking for feedback.
best regards
Luigi
Signed-off-by: Luigi Tarenga <luigi.tarenga(a)gmail.com>
---
include/rtl-sdr.h | 59 +++++++++++++++++++++++++
include/tuner_r82xx.h | 5 +++
src/librtlsdr.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++---
src/tuner_r82xx.c | 83 +++++++++++++++++++++++++++++++++++
4 files changed, 258 insertions(+), 7 deletions(-)
diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h
index fe64bea..3719df4 100644
--- a/include/rtl-sdr.h
+++ b/include/rtl-sdr.h
@@ -200,6 +200,65 @@ RTLSDR_API enum rtlsdr_tuner rtlsdr_get_tuner_type(rtlsdr_dev_t *dev);
RTLSDR_API int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains);
/*!
+ * Set the gain of a single gain stage for the device.
+ *
+ * Valid gain values may be queried with \ref rtlsdr_get_tuner_gain_stage_gains function.
+ * Usually those are from 0 to a positive integer plus -1 to set the stage in Auto gain mode.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param stage from 0 to number of gain stages minus 1.
+ * \param gain from 0 to maximum supported gain for selected stage or -1 to set Auto gain mode.
+ * \return 0 on success
+ */
+RTLSDR_API int rtlsdr_set_tuner_gain_stage(rtlsdr_dev_t *dev, int stage, int gain);
+
+
+/*!
+ * Get the gain of a single gain stage for the device.
+ *
+ * The value returned is a number from 0 to maximum supported gain. or -1 to indicate Auto gain mode.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param stage from 0 to number of gain stages minus 1.
+ * \return the gain value in a range from 0 to maximum supported gain or -1 if Auto gain mode.
+ */
+RTLSDR_API int rtlsdr_get_tuner_gain_stage(rtlsdr_dev_t *dev, int stage);
+
+
+/*!
+ * Get the number of gain stages supported by the device.
+ *
+ * The value returned is a number from 0 to the number of independent gain stages in the device.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \return the number of gain stages in the devices. 0 if none are supported.
+ */
+RTLSDR_API int rtlsdr_get_tuner_gain_stages(rtlsdr_dev_t *dev);
+
+/*!
+ * Get the supported values of gains in tenth of dB for a given stage.
+ *
+ * The value returned is the number of gain steps for the given stage and the maximum supported
+ * gain value plus one. The returned value -1 is the maximum value that
+ * can be used with \ref rtlsdr_set_tuner_gain_stage function as gain parameter.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param stage from 0 to number of gain stages minus 1.
+ * \param gains a pointer to an array of integer where supported dB steps will be copied. NULL for no copy.
+ * \return the number of gain steps for the given stage.
+ */
+RTLSDR_API int rtlsdr_get_tuner_gain_stage_gains(rtlsdr_dev_t *dev, int stage, int *gains);
+
+/*!
+ * Get the name of the given gain stage.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param stage from 0 to number of gain stages minus 1.
+ * \return the address of a NULL terminated char array containing a descriptive name of the give gain stage.
+ */
+RTLSDR_API const char* rtlsdr_get_tuner_gain_stage_name(rtlsdr_dev_t *dev, int stage);
+
+/*!
* Set the gain for the device.
* Manual gain mode must be enabled for this to work.
*
diff --git a/include/tuner_r82xx.h b/include/tuner_r82xx.h
index f6c206a..b21988d 100644
--- a/include/tuner_r82xx.h
+++ b/include/tuner_r82xx.h
@@ -115,6 +115,11 @@ int r82xx_standby(struct r82xx_priv *priv);
int r82xx_init(struct r82xx_priv *priv);
int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq);
int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain);
+int r82xx_set_gain_stage(struct r82xx_priv *priv, int stage, int gain);
+int r82xx_get_gain_stage(struct r82xx_priv *priv, int stage);
+int r82xx_get_gain_stages(struct r82xx_priv *priv);
+int r82xx_get_gain_stage_gains(struct r82xx_priv *priv, int stage, int *gains);
+const char *r82xx_get_gain_stage_name(struct r82xx_priv *priv, int stage);
int r82xx_set_bandwidth(struct r82xx_priv *priv, int bandwidth, uint32_t rate);
#endif
diff --git a/src/librtlsdr.c b/src/librtlsdr.c
index 9b7ba52..d0db745 100644
--- a/src/librtlsdr.c
+++ b/src/librtlsdr.c
@@ -64,6 +64,11 @@ typedef struct rtlsdr_tuner_iface {
int (*set_gain)(void *, int gain /* tenth dB */);
int (*set_if_gain)(void *, int stage, int gain /* tenth dB */);
int (*set_gain_mode)(void *, int manual);
+ int (*set_gain_stage)(void *, int stage, int gain);
+ int (*get_gain_stage)(void *, int stage);
+ int (*get_gain_stages)(void *);
+ int (*get_gain_stage_gains)(void *, int stage, int *gains);
+ const char * (*get_gain_stage_name)(void *, int stage);
} rtlsdr_tuner_iface_t;
enum rtlsdr_async_status {
@@ -258,45 +263,76 @@ int r820t_set_gain(void *dev, int gain) {
rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
return r82xx_set_gain(&devt->r82xx_p, 1, gain);
}
+
int r820t_set_gain_mode(void *dev, int manual) {
rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
return r82xx_set_gain(&devt->r82xx_p, manual, 0);
}
+int r820t_set_gain_stage(void *dev, int stage, int gain) {
+ rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
+ return r82xx_set_gain_stage(&devt->r82xx_p, stage, gain);
+}
+
+int r820t_get_gain_stage(void *dev, int stage) {
+ rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
+ return r82xx_get_gain_stage(&devt->r82xx_p, stage);
+}
+
+int r820t_get_gain_stages(void *dev) {
+ rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
+ return r82xx_get_gain_stages(&devt->r82xx_p);
+}
+
+int r820t_get_gain_stage_gains(void *dev, int stage, int *gains) {
+ rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
+ return r82xx_get_gain_stage_gains(&devt->r82xx_p, stage, gains);
+}
+
+const char *r820t_get_gain_stage_name(void *dev, int stage) {
+ rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
+ return r82xx_get_gain_stage_name(&devt->r82xx_p, stage);
+}
+
/* definition order must match enum rtlsdr_tuner */
static rtlsdr_tuner_iface_t tuners[] = {
{
- NULL, NULL, NULL, NULL, NULL, NULL, NULL /* dummy for unknown tuners */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* dummy for unknown tuners */
},
{
e4000_init, e4000_exit,
e4000_set_freq, e4000_set_bw, e4000_set_gain, e4000_set_if_gain,
- e4000_set_gain_mode
+ e4000_set_gain_mode, NULL, NULL, NULL, NULL, NULL
},
{
_fc0012_init, fc0012_exit,
fc0012_set_freq, fc0012_set_bw, _fc0012_set_gain, NULL,
- fc0012_set_gain_mode
+ fc0012_set_gain_mode, NULL, NULL, NULL, NULL, NULL
},
{
_fc0013_init, fc0013_exit,
fc0013_set_freq, fc0013_set_bw, _fc0013_set_gain, NULL,
- fc0013_set_gain_mode
+ fc0013_set_gain_mode, NULL, NULL, NULL, NULL, NULL
},
{
fc2580_init, fc2580_exit,
_fc2580_set_freq, fc2580_set_bw, fc2580_set_gain, NULL,
- fc2580_set_gain_mode
+ fc2580_set_gain_mode, NULL, NULL, NULL, NULL, NULL
},
{
r820t_init, r820t_exit,
r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL,
- r820t_set_gain_mode
+ r820t_set_gain_mode,
+ r820t_set_gain_stage,
+ r820t_get_gain_stage,
+ r820t_get_gain_stages,
+ r820t_get_gain_stage_gains,
+ r820t_get_gain_stage_name
},
{
r820t_init, r820t_exit,
r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL,
- r820t_set_gain_mode
+ r820t_set_gain_mode, NULL, NULL, NULL, NULL, NULL
},
};
@@ -1089,6 +1125,74 @@ int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int mode)
return r;
}
+int rtlsdr_set_tuner_gain_stage(rtlsdr_dev_t *dev, int stage, int gain)
+{
+ int r = 0;
+
+ if (!dev || !dev->tuner)
+ return -1;
+
+ if (dev->tuner->set_gain_stage) {
+ rtlsdr_set_i2c_repeater(dev, 1);
+ r = dev->tuner->set_gain_stage(dev, stage, gain);
+ rtlsdr_set_i2c_repeater(dev, 0);
+ }
+
+ return r;
+}
+
+int rtlsdr_get_tuner_gain_stage(rtlsdr_dev_t *dev, int stage)
+{
+ int r = 0;
+
+ if (!dev || !dev->tuner)
+ return -1;
+
+ if (dev->tuner->get_gain_stage)
+ r = dev->tuner->get_gain_stage(dev, stage);
+
+ return r;
+}
+
+int rtlsdr_get_tuner_gain_stages(rtlsdr_dev_t *dev)
+{
+ int r = 0;
+
+ if (!dev || !dev->tuner)
+ return -1;
+
+ if (dev->tuner->get_gain_stages)
+ r = dev->tuner->get_gain_stages(dev);
+
+ return r;
+}
+
+int rtlsdr_get_tuner_gain_stage_gains(rtlsdr_dev_t *dev, int stage, int *gains)
+{
+ int r = 0;
+
+ if (!dev || !dev->tuner)
+ return -1;
+
+ if (dev->tuner->get_gain_stage_gains)
+ r = dev->tuner->get_gain_stage_gains(dev, stage, gains);
+
+ return r;
+}
+
+const char *rtlsdr_get_tuner_gain_stage_name(rtlsdr_dev_t *dev, int stage)
+{
+ const char *r = "";
+
+ if (!dev || !dev->tuner)
+ return "";
+
+ if (dev->tuner->get_gain_stage_name)
+ r = dev->tuner->get_gain_stage_name(dev, stage);
+
+ return r;
+}
+
int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate)
{
int r = 0;
diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c
index f620238..8c9b5d1 100644
--- a/src/tuner_r82xx.c
+++ b/src/tuner_r82xx.c
@@ -1073,6 +1073,89 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain)
return 0;
}
+#define STAGE_NUM 3
+typedef struct r82xx_gain_stage {
+ const char *name;
+ const int *steps;
+ const int num;
+ int gain;
+} r82xx_gain_stage_t;
+
+
+static r82xx_gain_stage_t gain_stage[STAGE_NUM] = {
+ { "LNA", (int []) { 0, 9, 13, 40, 38, 13, 31, 22, 26, 31, 26, 14, 19, 5, 35, 13 }, 16, 0},
+ { "MIX", (int []) { 0, 5, 10, 10, 19, 9, 10, 25, 17, 10, 8, 16, 13, 6, 3, -8 }, 16, 0},
+ { "VGA", (int []) { 0, 26, 26, 30, 42, 35, 24, 13, 14, 32, 36, 34, 35, 37, 35, 36 }, 16, 0}
+};
+
+static const int r82xx_gain_stage_register[STAGE_NUM] = { 0x05, 0x07, 0x0c };
+static const int r82xx_gain_stage_mask[STAGE_NUM] = { 0x0f, 0x0f, 0x0f };
+static const int r82xx_gain_stage_manual[STAGE_NUM] = { 0x01, 0x00, 0x00 };
+static const int r82xx_gain_stage_manual_mask[STAGE_NUM] = { 0x10, 0x10, 0x10 };
+
+int r82xx_set_gain_stage(struct r82xx_priv *priv, int stage, int gain)
+{
+ int rc;
+
+ if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage))
+ return -1;
+
+ if (gain < -1 || gain >= gain_stage[stage].num)
+ return -1;
+
+ if (gain >= 0) {
+ /* stage auto off */
+ rc = r82xx_write_reg_mask(priv, r82xx_gain_stage_register[stage], r82xx_gain_stage_manual[stage], r82xx_gain_stage_manual_mask[stage]);
+ if (rc < 0)
+ return rc;
+
+ rc = r82xx_write_reg_mask(priv, r82xx_gain_stage_register[stage], (uint8_t) gain, r82xx_gain_stage_mask[stage]);
+ if (rc < 0)
+ return rc;
+
+ gain_stage[stage].gain = gain;
+ } else {
+ /* stage auto on */
+ rc = r82xx_write_reg_mask(priv, r82xx_gain_stage_register[stage], ~(r82xx_gain_stage_manual[stage]), r82xx_gain_stage_manual_mask[stage]);
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
+}
+
+int r82xx_get_gain_stage(struct r82xx_priv *priv, int stage)
+{
+ if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage))
+ return 0;
+
+ return gain_stage[stage].gain;
+}
+
+int r82xx_get_gain_stages(struct r82xx_priv *priv)
+{
+ return ARRAY_SIZE(gain_stage);
+}
+
+int r82xx_get_gain_stage_gains(struct r82xx_priv *priv, int stage, int *gains)
+{
+ if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage))
+ return -1;
+
+ if (gains)
+ memcpy(gains, gain_stage[stage].steps, gain_stage[stage].num * sizeof(int));
+
+ return gain_stage[stage].num;
+}
+
+const char *r82xx_get_gain_stage_name(struct r82xx_priv *priv, int stage)
+{
+ if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage))
+ return "";
+
+ return gain_stage[stage].name;
+}
+
/* Bandwidth contribution by low-pass filter. */
static const int r82xx_if_low_pass_bw_table[] = {
1700000, 1600000, 1550000, 1450000, 1200000, 900000, 700000, 550000, 450000, 350000
--
2.11.0
Here are some real beginner questions that I would like
to have a better understanding of concerning SDR in general and
the rtl dongles:
I understand that the I and Q signals are both 8-bit
numbers so each one can have 2^8 possible levels. Is the in-phase
value related to the amplitude of the signal such that frequency
variations within the pass band don't change it much?
Is the Q or Quadrature value something that varies with
whether or not the frequency is higher or lower than the center
frequency set in to the device?
I could imagine that if the Q value responds to changes
in frequency that one could get the effect of a discriminator
circuit.
I bought a couple of the rtl dongles and tried out the
rtl-fm program to receive local FM signals and it worked quite
well.
Finally, what determines the pass-band? It did seem to
get smaller if I tried a 12,000 HZ sample rate. I also was
surprised at how accurate the frequency is.
Other than the fact that I am at the low end of the
learning curve, I see all kinds of possibilities.
Martin McCormick WB5AGZ