Using the RTL2832 GPIO port

The RTL2832U chip has an 8bit GPIO port that can be used for things like switching antennas, filters, preamplifiers, attenuators...
(Once upon the time, we used the printer port for that, but these are gone...)

The GPIO port pins are kind of randomly thrown around the RTL2832U package:

P0 = pin 37
P1 = pin 32
P2 = pin 31
P3 = pin 36
P4 = pin 30
P5 = pin 29
P6 = pin 22
P7 = pin 21
In my R820T based dongle, none of them is used internally, and the pins are soldered to unconnected pads.
To connect to them, one must solder a thin (0.1mm) wire directly to the pins of the chip. It is best to also glue the wires to the top of the chip package, to improve mechanical strength.

The photo below shows 0.1mm wires soldered to P0 and P1, and mechanically fixed by a drop of cyanacrilate glue.

Wires attached to RTL2832

CAUTION: The port pins use 3.3V logic levels and are static sensitive!

In the rtlsdr library, src/librtlsdr.c already contains functions for port output, but they are not exported. To make them available, add
RTLSDR_API void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val);
RTLSDR_API void rtlsdr_set_gpio_output(rtlsdr_dev_t *dev, uint8_t gpio);
to the include/rtl-sdr.h file, and then do "make" and "make install".

Before using an GPIO pin as output, it must be put in output mode with:
rtlsdr_set_gpio_output(device, pin);
where pin is [0...7].
Then the state of the pin can be set with
rtlsdr_set_gpio_bit(device, pin, val);
where val is [0,1].

NOTE: There is an error in the (october 2015) rtlsdr_set_gpio_output() function. The direction bit should be written to GPD, not GPO!

There are no port input functions in src/librtlsdr.c, but it is easy to add them:

void rtlsdr_get_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int *val)
	uint16_t r;

	gpio = 1 << gpio;
	r = rtlsdr_read_reg(dev, SYSB, GPI, 1);
	*val = (r & gpio) ? 1 : 0;

void rtlsdr_set_gpio_input(rtlsdr_dev_t *dev, uint8_t gpio)
	int r;
	gpio = 1 << gpio;

	r = rtlsdr_read_reg(dev, SYSB, GPD, 1);
	rtlsdr_write_reg(dev, SYSB, GPD, r | gpio, 1);
	r = rtlsdr_read_reg(dev, SYSB, GPOE, 1);
	rtlsdr_write_reg(dev, SYSB, GPOE, r & ~gpio, 1);
and, of course into /include/rtl-sdr.h
RTLSDR_API void rtlsdr_get_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int *val);
RTLSDR_API void rtlsdr_set_gpio_input(rtlsdr_dev_t *dev, uint8_t gpio);
Usage is similar to the output funcions, first set the pin to input mode with
rtlsdr_set_gpio_input(device, pin);
where pin is [0...7].
Then the state of the pin can be read with
rtlsdr_get_gpio_bit(device, pin, &val);
where [0,1] will be returned in &val.

If more than one port pin should be changed or read simultaneously, something like this should work:
void rtlsdr_get_gpio_byte(rtlsdr_dev_t *dev, int *val)
	*val = rtlsdr_read_reg(dev, SYSB, GPI, 1);
void rtlsdr_set_gpio_byte(rtlsdr_dev_t *dev, int val)
	rtlsdr_write_reg(dev, SYSB, GPO, val);

Up to S57UUU Misc ham stuff page