浏览代码

introduce getters for tuner parameters (gain, type)

Dimitri Stolnikov 13 年之前
父节点
当前提交
7bd3933c41
共有 3 个文件被更改,包括 115 次插入29 次删除
  1. 30 0
      include/rtl-sdr.h
  2. 75 29
      src/librtlsdr.c
  3. 10 0
      src/rtl_test.c

+ 30 - 0
include/rtl-sdr.h

@@ -113,6 +113,34 @@ RTLSDR_API int rtlsdr_set_freq_correction(rtlsdr_dev_t *dev, int ppm);
 
 RTLSDR_API int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev);
 
+enum rtlsdr_tuner {
+	RTLSDR_TUNER_UNKNOWN = 0,
+	RTLSDR_TUNER_E4000,
+	RTLSDR_TUNER_FC0012,
+	RTLSDR_TUNER_FC0013,
+	RTLSDR_TUNER_FC2580
+};
+
+/*!
+ * Get the tuner type.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \return <= 0 on error, tuner type otherwise
+ */
+RTLSDR_API enum rtlsdr_tuner rtlsdr_get_tuner_type(rtlsdr_dev_t *dev);
+
+/*!
+ * Get a list of gains supported by the tuner.
+ *
+ * NOTE: The gains argument must be preallocated by the caller. If NULL is
+ * being given instead, the number of available gain values will be returned.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param gains array of gain values. In tenths of a dB, 115 means 11.5 dB.
+ * \return <= 0 on error, number of available (returned) gain values otherwise
+ */
+RTLSDR_API int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains);
+
 /*!
  * Set the gain for the device.
  * Manual gain mode must be enabled for this to work.
@@ -121,6 +149,8 @@ RTLSDR_API int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev);
  * -10, 15, 40, 65, 90, 115, 140, 165, 190,
  * 215, 240, 290, 340, 420, 430, 450, 470, 490
  *
+ * Valid gain values may be queried with \ref rtlsdr_get_tuner_gains function.
+ *
  * \param dev the device handle given by rtlsdr_open()
  * \param gain in tenths of a dB, 115 means 11.5 dB.
  * \return 0 on success

+ 75 - 29
src/librtlsdr.c

@@ -45,7 +45,7 @@
 #include "tuner_fc0013.h"
 #include "tuner_fc2580.h"
 
-typedef struct rtlsdr_tuner {
+typedef struct rtlsdr_tuner_iface {
 	/* tuner interface */
 	int (*init)(void *);
 	int (*exit)(void *);
@@ -53,7 +53,7 @@ typedef struct rtlsdr_tuner {
 	int (*set_bw)(void *, int bw /* Hz */);
 	int (*set_gain)(void *, int gain /* dB */);
 	int (*set_gain_mode)(void *, int manual);
-} rtlsdr_tuner_t;
+} rtlsdr_tuner_iface_t;
 
 enum rtlsdr_async_status {
 	RTLSDR_INACTIVE = 0,
@@ -75,7 +75,8 @@ struct rtlsdr_dev {
 	uint32_t rate; /* Hz */
 	uint32_t rtl_xtal; /* Hz */
 	/* tuner context */
-	rtlsdr_tuner_t *tuner;
+	enum rtlsdr_tuner tuner_type;
+	rtlsdr_tuner_iface_t *tuner;
 	uint32_t tun_xtal; /* Hz */
 	uint32_t freq; /* Hz */
 	int corr; /* ppm */
@@ -130,9 +131,7 @@ int fc0012_set_freq(void *dev, uint32_t freq) {
 	return fc0012_set_params(dev, freq, 6000000);
 }
 int fc0012_set_bw(void *dev, int bw) { return 0; }
-int _fc0012_set_gain(void *dev, int gain) {
-	return fc0012_set_gain(dev, gain);
-}
+int _fc0012_set_gain(void *dev, int gain) { return fc0012_set_gain(dev, gain); }
 int fc0012_set_gain_mode(void *dev, int manual) { return 0; }
 
 int _fc0013_init(void *dev) { return fc0013_init(dev); }
@@ -143,9 +142,7 @@ int fc0013_set_freq(void *dev, uint32_t freq) {
 	return fc0013_set_params(dev, freq, 6000000);
 }
 int fc0013_set_bw(void *dev, int bw) { return 0; }
-int _fc0013_set_gain(void *dev, int gain) {
-	return fc0013_set_gain(dev, gain);
-}
+int _fc0013_set_gain(void *dev, int gain) { return fc0013_set_gain(dev, gain); }
 int fc0013_set_gain_mode(void *dev, int manual) { return 0; }
 
 int fc2580_init(void *dev) { return fc2580_Initialize(dev); }
@@ -153,20 +150,15 @@ int fc2580_exit(void *dev) { return 0; }
 int _fc2580_set_freq(void *dev, uint32_t freq) {
 	return fc2580_SetRfFreqHz(dev, freq);
 }
-int fc2580_set_bw(void *dev, int bw) {
-	return fc2580_SetBandwidthMode(dev, 1);
-}
+int fc2580_set_bw(void *dev, int bw) { return fc2580_SetBandwidthMode(dev, 1); }
 int fc2580_set_gain(void *dev, int gain) { return 0; }
 int fc2580_set_gain_mode(void *dev, int manual) { return 0; }
 
-enum rtlsdr_tuners {
-	RTLSDR_TUNER_E4000,
-	RTLSDR_TUNER_FC0012,
-	RTLSDR_TUNER_FC0013,
-	RTLSDR_TUNER_FC2580
-};
-
-static rtlsdr_tuner_t tuners[] = {
+/* definition order must match enum rtlsdr_tuner */
+static rtlsdr_tuner_iface_t tuners[] = {
+	{
+		NULL, NULL, NULL, NULL, NULL, NULL /* dummy for unknown tuners */
+	},
 	{
 		e4000_init, e4000_exit,
 		e4000_set_freq, e4000_set_bw, e4000_set_gain,
@@ -673,6 +665,56 @@ int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev)
 	return dev->corr;
 }
 
+enum rtlsdr_tuner rtlsdr_get_tuner_type(rtlsdr_dev_t *dev)
+{
+	if (!dev)
+		return -1;
+
+	return dev->tuner_type;
+}
+
+int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains)
+{
+	const int e4k_gains[] = { -10, 15, 40, 65, 90, 115, 140, 165, 190, 215,
+				  240, 290, 340, 420, 430, 450, 470, 490 };
+	const int fc0012_gains[] = { 0 /* no gain values */ };
+	const int fc0013_gains[] = { -63, 71, 191, 197 };
+	const int fc2580_gains[] = { 0 /* no gain values */ };
+
+	int *ptr = NULL;
+	int len = 0;
+
+	if (!dev)
+		return -1;
+
+	switch (dev->tuner_type) {
+	case RTLSDR_TUNER_E4000:
+		ptr = (int *)e4k_gains; len = sizeof(e4k_gains);
+		break;
+	case RTLSDR_TUNER_FC0012:
+		ptr = (int *)fc0012_gains; len = sizeof(fc0012_gains);
+		break;
+	case RTLSDR_TUNER_FC0013:
+		ptr = (int *)fc0013_gains; len = sizeof(fc0013_gains);
+		break;
+	case RTLSDR_TUNER_FC2580:
+		ptr = (int *)fc2580_gains; len = sizeof(fc2580_gains);
+		break;
+	default:
+		fprintf(stderr, "Invalid tuner type %d\n", dev->tuner_type);
+		break;
+	}
+
+	if (!gains) { /* no buffer provided, just return the count */
+		return len / sizeof(int);
+	} else {
+		if (len)
+			memcpy(gains, ptr, len);
+
+		return len / sizeof(int);
+	}
+}
+
 int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain)
 {
 	int r = 0;
@@ -972,7 +1014,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
 	reg = rtlsdr_i2c_read_reg(dev, E4K_I2C_ADDR, E4K_CHECK_ADDR);
 	if (reg == E4K_CHECK_VAL) {
 		fprintf(stderr, "Found Elonics E4000 tuner\n");
-		dev->tuner = &tuners[RTLSDR_TUNER_E4000];
+		dev->tuner_type = RTLSDR_TUNER_E4000;
 		goto found;
 	}
 
@@ -980,7 +1022,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
 	if (reg == FC0013_CHECK_VAL) {
 		fprintf(stderr, "Found Fitipower FC0013 tuner\n");
 		rtlsdr_set_gpio_output(dev, 6);
-		dev->tuner = &tuners[RTLSDR_TUNER_FC0013];
+		dev->tuner_type = RTLSDR_TUNER_FC0013;
 		goto found;
 	}
 
@@ -994,7 +1036,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
 	reg = rtlsdr_i2c_read_reg(dev, FC2580_I2C_ADDR, FC2580_CHECK_ADDR);
 	if ((reg & 0x7f) == FC2580_CHECK_VAL) {
 		fprintf(stderr, "Found FCI 2580 tuner\n");
-		dev->tuner = &tuners[RTLSDR_TUNER_FC2580];
+		dev->tuner_type = RTLSDR_TUNER_FC2580;
 		goto found;
 	}
 
@@ -1002,18 +1044,22 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
 	if (reg == FC0012_CHECK_VAL) {
 		fprintf(stderr, "Found Fitipower FC0012 tuner\n");
 		rtlsdr_set_gpio_output(dev, 6);
-		dev->tuner = &tuners[RTLSDR_TUNER_FC0012];
+		dev->tuner_type = RTLSDR_TUNER_FC0012;
 		goto found;
 	}
 
 found:
-	if (dev->tuner) {
-		dev->tun_xtal = dev->rtl_xtal;
-
-		if (dev->tuner->init)
-			r = dev->tuner->init(dev);
+	if (dev->tuner_type == RTLSDR_TUNER_UNKNOWN) {
+		r = -1;
+		goto err;
 	}
 
+	dev->tuner = &tuners[dev->tuner_type];
+	dev->tun_xtal = dev->rtl_xtal;
+
+	if (dev->tuner->init)
+		r = dev->tuner->init(dev);
+
 	rtlsdr_set_i2c_repeater(dev, 0);
 
 	*out_dev = dev;

+ 10 - 0
src/rtl_test.c

@@ -160,6 +160,8 @@ int main(int argc, char **argv)
 	uint32_t samp_rate = DEFAULT_SAMPLE_RATE;
 	uint32_t out_block_size = DEFAULT_BUF_LENGTH;
 	int device_count;
+	int count;
+	int gains[100];
 
 	while ((opt = getopt(argc, argv, "d:s:b:tS::")) != -1) {
 		switch (opt) {
@@ -228,6 +230,14 @@ int main(int argc, char **argv)
 #else
 	SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
 #endif
+	count = rtlsdr_get_tuner_gains(dev, NULL);
+	fprintf(stderr, "Supported gain values (%d): ", count);
+
+	count = rtlsdr_get_tuner_gains(dev, gains);
+	for (i = 0; i < count; i++)
+		fprintf(stderr, "%.1f ", gains[i] / 10.0);
+	fprintf(stderr, "\n");
+
 	/* Set the sample rate */
 	r = rtlsdr_set_sample_rate(dev, samp_rate);
 	if (r < 0)