# ms-jdow/rtlsdr-Cplusplus-VS2010

MS Visual Studio version of the Oliver Jowett branch for rtlsdr.dll. This version is in C++ with slight additional functonality.
msjdow This solves it and enshrines the debugging changes that proved what w…
…as happening.

Signed-off-by: msjdow <msjdow@users.noreply.github.com>
Latest commit b9fd3cf Apr 17, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
Common Mar 21, 2018
RtlSdr Catalog Mar 21, 2018
libusb Mar 21, 2018
.gitignore Mar 21, 2018
AUTHORS Nov 18, 2016
COPYING Dec 29, 2014
IRtlSdr.h Mar 21, 2018
ITuner.h Mar 21, 2018
User Notes.txt Mar 21, 2018
dllmain.cpp Mar 21, 2018
librtlsdr.cpp Apr 17, 2018
librtlsdr.h Mar 21, 2018
librtlsdr_dongle_comms.cpp Mar 21, 2018
librtlsdr_dongle_comms.h Mar 21, 2018
librtlsdr_registryAndNames.cpp Apr 17, 2018
librtlsdr_registryAndNames.h Mar 21, 2018
resource.h Mar 21, 2018
rtl-sdr.h Mar 21, 2018
rtl-sdr_export.h Oct 26, 2016
rtlsdr.rc Mar 21, 2018
rtlsdr_app.cpp Mar 21, 2018
rtlsdr_app.h Mar 21, 2018
rtsdr.sln Mar 21, 2018
rtsdr.vcxproj Mar 21, 2018
rtsdr.vcxproj.filters Mar 21, 2018
stdafx.cpp Mar 21, 2018
stdafx.h Mar 21, 2018
targetver.h Mar 21, 2018
tuner_Dummy.h Mar 21, 2018
tuner_e4k.cpp Mar 21, 2018
tuner_e4k.h Mar 21, 2018
tuner_fc0012.cpp Mar 21, 2018
tuner_fc0012.h Mar 21, 2018
tuner_fc0013.cpp Mar 21, 2018
tuner_fc0013.h Mar 21, 2018
tuner_fc2580.cpp Mar 21, 2018
tuner_fc2580.h Mar 21, 2018
tuner_r82xx.cpp Mar 21, 2018
tuner_r82xx.h Mar 21, 2018

rtl-sdr
======================================================================

http://sdr.osmocom.org/trac/wiki/rtl-sdr

Notes on the mutability tree (2014/09/29)
=========================================

Since there seems to be some wider interest in this, some quick notes on
my changes here.

TL;DR:

0Hz
.
.  "no mod direct sampling"
.  no mixing at all, tuner is mostly disabled, just ram as much signal
.  as you can at it and maybe some will leak through.
.  YMMV a lot
.
~13MHz  (PLL lower limit - 14MHz)
.
.  normal tuning, large IF.
.  high-side mixing
.  you will see nasty aliasing / attentuation / harmonics
.  near the lower edge of the range
.  you will see lots of noise from the dongle itself near 14.4MHz
.
~21MHz  (PLL lower limit - 6MHz)   <- upstream tuner lower limit
.
.  normal tuning, regular IF
.  high-side mixing
.  this should behave much like upstream
.
~1844Mhz (PLL upper limit - 6MHz)  <- upstream tuner upper limit
.
.  normal tuning, small IF (getting squashed against the PLL upper bound)
.  high-side mixing
.
~1848MHz (PLL upper limit - 2MHz)
.
.  tuning with low-side mixing (PLL frequency below tuned frequency)
.  you will see nasty aliasing / attentuation / harmonics
.  near the upper edge of the range
.
~1864MHz (PLL upper limit + 14MHz) <- that's all, folks

(PLL limits vary by dongle - some go as high as 1885MHz)

This tree is a collection of random tuner hacks which are really exploratory
more than anything. They may or may not work for you.

First some background for those unfamiliar with the internals of the dongle:

* The R820T tuner has a tunable PLL that can generate frequencies between
around 27MHz .. 1850MHz. The exact range varies from dongle to dongle.
* The tuner mixes the incoming RF signal with this PLL output. This shifts
the RF signal down to a frequency that is the difference between the PLL
frequency and the RF signal's frequency.
* The tuner sends this intermediate frequency (IF) signal to the RTL2838U
* The RTL2838U digitizes the IF signal and does a digital downconversion
step to generate I/Q samples that are centered around "zero". The
downconverter can theoretically handle IF signals up to 14.4MHz.

The main change is to feed information about the actually-tuned frequency back
from the tuner (R820T) code to the core (RTL2832U) code, allowing the core
code to adjust to the actual IF in use, rather than requiring a fixed IF. The
core code has also been taught how to handle low-side mixing, where the PLL
frequency is lower than the requested frequency (e.g. the spectrum inversion
changes then)

When tuning, the R820T tuner will try to tune to the requested frequency +
6MHz, producing a 6MHz IF. If the PLL cannot handle that frequency, the tuner
will try a few things to produce something useful.

At the top of the tuning range:

* It will tune as high as it can go normally, then stick there producing a
smaller effective IF as the requested frequency gets higher and higher.
* Once the IF starts getting too small (below about 1.5MHz things start to
go bad), it will switch to low-side mixing and try to put the PLL frequency
*below* the target frequency. This gives you another 14-15 MHz at the top
of the range.

I've had reports that some dongles can tune to within a whisker of 2000MHz
with this.

At the bottom of the range:

* It will tune as low as it can go normally, then stick there producing a
larger effective IF as the requested frequency gets lower and lower.
* Once the required IF exceeds 14.4MHz, it will switch to a variant of tejeez'
et al "no mod direct sampling" mode. This essentially disables the PLL in
the tuner entirely, and relies on some RF signal leaking through the tuner
unchanged. The tuner claims to be tuned to 0Hz in this mode, and the core
does all the real tuning. The dongle is almost deaf in this mode, you will
have to turn the RF gain WAY UP. You do not need to mess with direct sampling
settings to enable this, it's integrated with normal tuning.

The success of the "no mod direct sampling" mode seems to vary a lot from dongle
to dongle. Mine is almost completely deaf so I can't test this much. Others have
had success in tuning to shortwave stations as low as 3.5MHz.

The actual PLL limits vary from dongle to dongle, and from day to day (they're
probably temperature related). The tuner has three sets of tuning limits:

* a hardcoded "do not exceed this" set of limits - see PLL_INITIAL_LOW /
PLL_INITIAL_HIGH in tuner_r82xx.c. These are in place because, especially at
the low end of the range, the PLL can get into a state where you ask for (for
example) 25MHz, the PLL claims to be locked OK at that frequency, but in
reality it's actually producing 27MHz, which screws up the core's calculations
of the IF offset needed.
* a hardcoded "known to be OK" set of limits - see PLL_SAFE_LOW / PLL_SAFE_HIGH
in tuner_r82xx.c. This is a range where the PLL should always work; if the PLL
doesn't work in this range it is treated as a tuning error and tuning fails.
* a runtime "seems to be OK at the moment" set of limits. This varies from run
to run and initially starts at the "do not exceed" limits. Whenever a failure
to get PLL lock is seen, the runtime limits are shrunk accordingly and we try
again. This allows the tuner to adapt to the particular dongle in use.

Remember that at the extreme edges of these ranges you will be fighting an uphill
battle against the dongle design itself, as you will be far out of the intended
range of the filters etc and nothing works particularly well.

You are likely to see small frequency shifts (maybe 1-2ppm) from what you get in
upstream. This is because the tuner+2832 combination can be tuned a little more
accurately than upstream does, so some errors that you will have previously been
correcting for will disappear.

-- Oliver (oliver.jowett@gmail.com / oliver@mutability.co.uk)

Notes on the Joanne Dow tree (2014/10/24)
=========================================

This tree is based on the mutability tree above. The changes involve making it a
Windows specific tool, converting it to VS2010, converting it to C++, and adding
a feature for supporting multiple dongles. Converting it back to work on 'ix should
not be particularly difficult as long as you accept that it's in C++. As it sits it
is 100% compatible with the base rtlsdr.dll.

The added feature gives this version the ability to always know a dongle's
particulars even if the dongle is busy. The best way to start using it is to
replace all instances of the old rtlsdr.dll with this one. (Rename the old to
make going back easier, if you find problems.) This has a pleasant side effect of
requiring that you close all programs using the rtlsdr.dlls that you replace.

Now when you open a program that uses the dongles when ever dongles are enumerated
and some of the time when USB strings are read the polled data is reconciled with
any data saved in the Windows registry. When the poll is completed and reconciled
it is written to the Windows registry and locally cached.

When a dongle is busy and its strings are requested the name is pulled from the
local registry cache, an * is prefixed to the manufacturer string, and the results
are returned to the main program. As a result you never get the embarrassing mess
the base rtlsdr.dll leaves in tools like rtl_sdr.exe and rtl_tcp.exe.

The information stored in the registry for each dongle contains the following:
This version uses the Windows Registry to store USB string and path parameters
for all discovered. Parameters stored are as follows:
BYTE    string1[ 256 ];				//	Null terminated Manufacturer ID string
BYTE	string2[ 256 ];				//	Null terminated Product ID string
BYTE	string3[ 256 ];				//	Null terminated Serial Number ID string
WORD	mid;						//	Manufacturer ID word
WORD	pid;						//	Product ID word.
BYTE	usbpath[ MAX_USB_PATH ];	//	Stores USB path through hubs to device
char	unusedc;					//	Ignored.
bool	unusedb;					//	Ignored.
BYTE	devindex;					//	LibUsb index for this device.
BYTE	iManufacturer;				//	Index of manufacturer string
BYTE	iProduct;					//	Index of product string
BYTE	iSerialNumber;				//	Index of serial number string
BYTE	tunerType;					//	Type of tuner per enum rtlsdr_tuner

This version also features the option to directly access the rtlsdr class that is
created and used by the classic static librtlsdr entry points. Some slight extra
functionality is available. See librtlsdr.h for details.

Notes on the Joanne Dow tree (2016/10/26)
=========================================

A variant on Leif Asbrink's excellent filter work has been included in this
new version. These changes enable a variety of narrower analog filters that can
reduce large signals that are causing problems and are far enough away from
interfering signals. The basic entry points Leif generated behave the same. A
new interface allows selection between sets of filters with different design
philosophies. Only two sets are supported in this version, Leif's filters, which
are offset to avoid the center spike if possible, and filters I generated which
are centered around the center of the sampled bandwidth.

New entry points supported:
/*!
* Get a list of bandwidths supported by the tuner.
*
* NOTE: The bandwidths argument must be preallocated by the caller. If NULL is
* being given instead, the number of available bandwidth values will be returned.
*
* \param dev the device handle given by rtlsdr_open()
* \param bandwidths array of bandwidth values in Hz.
* \return <= 0 on error, number of available (returned) gain values otherwise
*/
RTLSDR_API int rtlsdr_get_tuner_bandwidths(rtlsdr_dev_t *dev, int *bandwidths);

/*!
* Set the bandwidth for the device.
*
* Valid bandwidth values may be queried with \ref rtlsdr_get_tuner_bandwidths function.
*
* \param dev the device handle given by rtlsdr_open()
* \param bandwidth in Hz.
* \return 0 on success
*/
RTLSDR_API int rtlsdr_set_tuner_bandwidth(rtlsdr_dev_t *dev, int bandwidth);

/*!
*	Get the name for a set of IF filter bandwidths
*
*	Query for bandwidth set N's name. Repeat for all values until the return
*	value is -1.
*
*	\param dev the device handle given by rtlsdr_open()
*	\param nSet the index for the set to be recovered.
*	\param pString pointer to 80 BYTEs of storage to hold the bandwidth name.
*	\return 0 on success else -1.
*/
RTLSDR_API int rtlsdr_get_bandwidth_set_name( rtlsdr_dev_t *dev
, int nSet
, char* pString
);

/*!
*	Select the IF bandwdith set desired.
*
*	Set a new current value for the bandwidth set in use. Follow with a query
*	for bandwidths in the set using rtlsdr_get_tuner_bandwidths().
*
* \param dev the device handle given by rtlsdr_open()
* \param nSet Bandwidth set number
* \return 0 on success -1 on error.
*/
RTLSDR_API int rtlsdr_set_bandwidth_set( rtlsdr_dev_t *dev, int nSet );

#if defined( SET_SPECIAL_FILTER_VALUES )	// For testing
RTLSDR_API int rtlsdr_set_if_values		( rtlsdr_dev_t *dev
, BYTE			regA
, BYTE			regB
, DWORD			ifFreq
);

#endif

The last entry point is conditionally compiled and supports exploring the
filter settings to generate new sets of filters.

Notes on the Joanne Dow tree (2016/11/18)
=========================================

This version adds bias tee setting and an automated direct sampling mode.
As a note to the developer some of the basic features now interact with
each other. It is best to set a dummy frequency value first, then the other
variables pretty much in the order seen in the new rtlsdr_do_direct_sampling
function. That way everything is initialized properly.

New entry points include:
/*!
* Get a list of bandwidths supported by the tuner.
*
* NOTE: The bandwidths argument must be preallocated by the caller. If NULL is
* being given instead, the number of available bandwidth values will be returned.
*
* \param dev the device handle given by rtlsdr_open()
* \param bandwidths array of bandwidth values in Hz.
* \return <= 0 on error, number of available (returned) gain values otherwise
*/
RTLSDR_API int rtlsdr_get_tuner_bandwidths(rtlsdr_dev_t *dev, int *bandwidths);

/*!
* Set the bandwidth for the device.
*
* Valid bandwidth values may be queried with \ref rtlsdr_get_tuner_bandwidths function.
*
* \param dev the device handle given by rtlsdr_open()
* \param bandwidth in Hz.
* \return 0 on success
*/
RTLSDR_API int rtlsdr_set_tuner_bandwidth(rtlsdr_dev_t *dev, int bandwidth);

/*!
*	Get the name for a set of IF filter bandwidths
*
*	Query for bandwidth set N's name. Repeat for all values until the return
*	value is -1.
*
*	\param dev the device handle given by rtlsdr_open()
*	\param nSet the index for the set to be recovered.
*	\param pString pointer to 80 BYTEs of storage to hold the bandwidth name.
*	\return 0 on success else -1.
*/
RTLSDR_API int rtlsdr_get_bandwidth_set_name( rtlsdr_dev_t *dev
, int nSet
, char* pString
);

/*!
*	Select the IF bandwdith set desired.
*
*	Set a new current value for the bandwidth set in use. Follow with a query
*	for bandwidths in the set using rtlsdr_get_tuner_bandwidths().
*
* \param dev the device handle given by rtlsdr_open()
* \param nSet Bandwidth set number
* \return 0 on success -1 on error.
*/
RTLSDR_API int rtlsdr_set_bandwidth_set( rtlsdr_dev_t *dev, int nSet );

/*!
* Enable or disable the bias tee on GPIO PIN 0.
*/
RTLSDR_API int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on);