diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h index a3256ec..6bb6fc2 100755 --- a/include/rtl-sdr.h +++ b/include/rtl-sdr.h @@ -475,6 +475,19 @@ RTLSDR_API int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on); */ RTLSDR_API int rtlsdr_set_opt_string(rtlsdr_dev_t *dev, const char *opts, int verbose); + +/*! + * Exposes/permits hacking of Tuner-specific I2C registers + * + * \param dev the device handle given by rtlsdr_open() + * \param i2c_register 1 for Bias T on. 0 for Bias T off. + * \param mask 8-bit bitmask, indicating which bits shall be set + * \param data 8-bit data, which shall be set + * \return -1 if device is not initialized. 0 otherwise. + */ +RTLSDR_API int rtlsdr_set_tuner_i2c_register(rtlsdr_dev_t *dev, unsigned i2c_register, unsigned mask, unsigned data); + + #ifdef __cplusplus } #endif diff --git a/include/rtl_tcp.h b/include/rtl_tcp.h index 19dc8fd..c57b938 100644 --- a/include/rtl_tcp.h +++ b/include/rtl_tcp.h @@ -26,6 +26,9 @@ extern "C" { /*! * This enum defines the possible commands in rtl_tcp + * commands 0x01..0x0E are compatible to osmocom's rtlsdr + * see https://github.com/osmocom/rtl-sdr/blob/master/src/rtl_tcp.c + * commands >= 0x40 are extensions */ enum RTL_TCP_COMMANDS { SET_FREQUENCY = 0x01, @@ -44,7 +47,8 @@ enum RTL_TCP_COMMANDS { SET_BIAS_TEE = 0x0E, SET_TUNER_BANDWIDTH = 0x40, UDP_ESTABLISH = 0x41, - UDP_TERMINATE = 0x42 + UDP_TERMINATE = 0x42, + SET_I2C_TUNER_REGISTER = 0x43 /* for experiments: data: 31 .. 16: register; 15 .. 8: mask; 7 .. 0: data */ }; #ifdef __cplusplus diff --git a/include/tuner_r82xx.h b/include/tuner_r82xx.h index a940731..6cf7030 100755 --- a/include/tuner_r82xx.h +++ b/include/tuner_r82xx.h @@ -114,6 +114,7 @@ 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(struct r82xx_priv *priv, int set_manual_gain, int gain, int extended_mode, int lna_gain, int mixer_gain, int vga_gain); +int r82xx_set_i2c_register(struct r82xx_priv *priv, unsigned i2c_register, unsigned mask, unsigned data); int r82xx_set_bandwidth(struct r82xx_priv *priv, int bandwidth, uint32_t rate, uint32_t * applied_bw, int apply); diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 0d4bc20..8dd9405 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -74,6 +74,7 @@ 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_i2c_register)(void *, unsigned i2c_register, unsigned mask /* byte */, unsigned data /* byte */ ); } rtlsdr_tuner_iface_t; enum rtlsdr_async_status { @@ -344,40 +345,46 @@ int r820t_set_gain_mode(void *dev, int manual) { return r82xx_set_gain(&devt->r82xx_p, manual, 0, 0, 0, 0, 0); } +int r820t_set_i2c_register(void *dev, unsigned i2c_register, unsigned mask, unsigned data ) { + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; + return r82xx_set_i2c_register(&devt->r82xx_p, i2c_register, mask, data); +} + + /* 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 /* 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 }, { _fc0012_init, fc0012_exit, fc0012_set_freq, fc0012_set_bw, _fc0012_set_gain, NULL, - fc0012_set_gain_mode + fc0012_set_gain_mode, NULL }, { _fc0013_init, fc0013_exit, fc0013_set_freq, fc0013_set_bw, _fc0013_set_gain, NULL, - fc0013_set_gain_mode + fc0013_set_gain_mode, NULL }, { fc2580_init, fc2580_exit, _fc2580_set_freq, fc2580_set_bw, fc2580_set_gain, NULL, - fc2580_set_gain_mode + fc2580_set_gain_mode, 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_i2c_register }, { r820t_init, r820t_exit, r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL, - r820t_set_gain_mode + r820t_set_gain_mode, r820t_set_i2c_register }, }; @@ -1409,6 +1416,30 @@ int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int mode) return r; } +int rtlsdr_set_tuner_i2c_register(rtlsdr_dev_t *dev, unsigned i2c_register, unsigned mask /* byte */, unsigned data /* byte */ ) +{ + int r = 0; + + #ifdef _ENABLE_RPC + if (rtlsdr_rpc_is_enabled()) + { + /* TODO */ + return -1; + } + #endif + + if (!dev || !dev->tuner) + return -1; + + if (dev->tuner->set_i2c_register) { + rtlsdr_set_i2c_repeater(dev, 1); + r = dev->tuner->set_i2c_register((void *)dev, i2c_register, mask, data); + rtlsdr_set_i2c_repeater(dev, 0); + } + 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 0f883f0..3444e0f 100644 --- a/src/tuner_r82xx.c +++ b/src/tuner_r82xx.c @@ -1134,6 +1134,16 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain, } +/* expose/permit tuner specific i2c register hacking! */ +int r82xx_set_i2c_register(struct r82xx_priv *priv, unsigned i2c_register, unsigned mask, unsigned data) +{ + uint8_t reg = i2c_register & 0xFF; + uint8_t reg_mask = mask & 0xFF; + uint8_t reg_val = data & 0xFF; + return r82xx_write_reg_mask(priv, reg, reg_val, reg_mask); +} + + /* 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