gr-baz Package
rtl2832.h
Go to the documentation of this file.
00001 #ifndef INCLUDED_RTL2832
00002 #define INCLUDED_RTL2832
00003 
00004 #include <stdio.h>
00005 #include <stdarg.h>
00006 
00007 #ifdef LIBUSB_FOUND
00008 #include <libusb-1.0/libusb.h>
00009 #else
00010 #include <libusb/libusb.h>      // libusbx on Windows
00011 #endif // LIBUSB_FOUND
00012 
00013 #ifdef _WIN32
00014 
00015 #ifdef RTL2832_EXPORTS
00016 #define RTL2832_API                     __declspec(dllexport)
00017 #else
00018 #define RTL2832_API                     __declspec(dllimport)
00019 #endif
00020 
00021 // 'libusb.h' offers uint8_t & uint16_t
00022 typedef __int8   int8_t;
00023 typedef unsigned int uint32_t;
00024 typedef unsigned __int64 uint64_t;
00025 
00026 #else
00027 
00028 #define RTL2832_API
00029 #define RTL2832_TEMPLATE
00030 
00031 #endif // _WIN32
00032 
00033 #include <vector>
00034 #include <map>
00035 #include <string>
00036 
00037 RTL2832_API extern int get_map_index(int value, const int* map, int pair_count);
00038 RTL2832_API extern const char* libusb_result_to_string(int res);
00039 
00040 #ifdef _WIN32
00041 #define CURRENT_FUNCTION        __FUNCTION__
00042 #else
00043 #define CURRENT_FUNCTION        __PRETTY_FUNCTION__
00044 #endif // _WIN32
00045 
00046 // Swap following comments to disable I2C reporting
00047 //#define DEBUG_TUNER_I2C(t,r)  // This is empty on purpose
00048 #define DEBUG_TUNER_I2C(t,r) \
00049         if (t->params().message_output && function && (line_number >= 0) && (line)) \
00050                 t->params().message_output->on_log_message_ex(RTL2832_NAMESPACE::log_sink::LOG_LEVEL_ERROR, "%s: %s [%i] @ %s:%i \"%s\"\n", __FUNCTION__, libusb_result_to_string(r), r, function, line_number, line);
00051 
00052 #define RTL2832_NAMESPACE       rtl2832
00053 
00054 namespace RTL2832_NAMESPACE
00055 {
00056 
00057 class demod;
00058 
00059 enum result_code
00060 {
00061         // < 0: libusb result code
00062         FAILURE = 0,
00063         SUCCESS = 1     // > 0 also # bytes transferred
00064 };
00065 
00066 #define TUNERS_NAMESPACE        tuners
00067 
00068 #define TUNER_FACTORY_FN_NAME   Factory
00069 #define TUNER_PROBE_FN_NAME             Probe
00070 #define DECLARE_TUNER_FACTORY() \
00071         public: \
00072         static tuner* TUNER_FACTORY_FN_NAME(demod* p);  \
00073         static int TUNER_PROBE_FN_NAME(demod* d);
00074 #define IMPLEMENT_TUNER_FACTORY(class_name) \
00075         tuner* class_name::TUNER_FACTORY_FN_NAME(demod* p) \
00076         { return new class_name(p); }
00077 #define IMPLEMENT_INLINE_TUNER_FACTORY(class_name) \
00078         public: \
00079         static tuner* TUNER_FACTORY_FN_NAME(demod* p) \
00080         { return new class_name(p); } \
00081         static int TUNER_PROBE_FN_NAME(demod* d);
00082 
00083 // _WIN32: DLL WARNING! These will cause C4251, but only 'vector' can be exported as a DLL interface. You must have exactly the same STL headers in your importing files, otherwise your app will crash. Solution is to recompile this library with your own STL headers.
00084 typedef std::pair<double,double> range_t;
00085 typedef std::vector<double> values_t;
00086 typedef std::map<int,std::string> num_name_map_t;
00087 
00088 inline bool values_to_range(const values_t& v, range_t& r)
00089 { if (v.empty()) return false; r = std::make_pair(v[0], v[v.size() - 1]); return true; }
00090 
00091 inline bool is_valid_range(const range_t& r)
00092 { return !(r.first == r.second); }
00093 
00094 inline bool in_range(const range_t& r, double d)
00095 { return !((d < r.first) || (d > r.second)); }
00096 
00097 inline bool in_valid_range(const range_t& r, double d)  // If invalid range, return 'true'
00098 { return ((is_valid_range(r) == false) || (in_range(r, d))); }
00099 
00100 inline double calc_range(const range_t& r)
00101 { return (r.second - r.first); }
00102 
00103 class log_sink
00104 {
00105 public:
00106         enum level
00107         {
00108                 LOG_LEVEL_ERROR         = -1,   // Negative: more serious
00109                 LOG_LEVEL_DEFAULT       = 0,
00110                 LOG_LEVEL_VERBOSE       = 1,    // Positive: more verbose
00111         };
00112 public:
00113         virtual void on_log_message_va(int level, const char* msg, va_list args)=0;
00114 public:
00115         inline virtual void on_log_message(const char* msg, ...)
00116         { va_list args; va_start(args, msg); on_log_message_va(LOG_LEVEL_DEFAULT, msg, args); }
00117         inline virtual void on_log_message_ex(int level, const char* msg, ...)
00118         { va_list args; va_start(args, msg); on_log_message_va(level, msg, args); }
00119 };
00120 
00121 class i2c_interface
00122 {
00123 public:
00124         virtual int set_i2c_repeater(bool on = true, const char* function_name = NULL, int line_number = -1, const char* line = NULL)=0;
00125         virtual int i2c_read(uint8_t i2c_addr, uint8_t *buffer, int len)=0;
00126         virtual int i2c_write(uint8_t i2c_addr, uint8_t *buffer, int len)=0;
00127         virtual int i2c_write_reg(uint8_t i2c_addr, uint8_t reg, uint8_t val)=0;
00128         virtual int i2c_read_reg(uint8_t i2c_addr, uint8_t reg, uint8_t& data)=0;
00129 };
00130 
00131 class named_interface
00132 {
00133 public:
00134         virtual const char* name() const=0;
00135 };
00136 
00137 class RTL2832_API tuner : public i2c_interface, public named_interface
00138 {
00139 public:
00140         virtual ~tuner();
00141 public:
00142         typedef tuner* (*CreateTunerFn)(demod* p);
00143         typedef int (*ProbeTunerFn)(demod* p);
00144         typedef struct params
00145         {
00146                 log_sink*       message_output;
00147                 bool            verbose;
00148         } PARAMS, *PPARAMS;
00149         enum gain_mode {
00150                 NOT_SUPPORTED   = -1,
00151                 DEFAULT                 = 0,
00152                 // Specific values > 0 & internal to tuner implementations
00153         };
00154 public:
00155         virtual int initialise(PPARAMS params = NULL)=0;
00156         //virtual const char* name()=0;
00157         virtual int set_frequency(double freq)=0;
00158         virtual int set_bandwidth(double bw)=0;
00159         virtual int set_gain(double gain)=0;
00160         virtual int set_gain_mode(int mode)=0;
00161         virtual int set_auto_gain_mode(bool on = true)=0;
00162 public:
00163         virtual int set_i2c_repeater(bool on = true, const char* function_name = NULL, int line_number = -1, const char* line = NULL)=0;
00164         virtual int i2c_read(uint8_t i2c_addr, uint8_t *buffer, int len)=0;
00165         virtual int i2c_write(uint8_t i2c_addr, uint8_t *buffer, int len)=0;
00166 public:
00167         virtual double frequency() const=0;
00168         virtual double bandwidth() const=0;
00169         virtual double gain() const=0;
00170         virtual int gain_mode() const=0;
00171 public:
00172         virtual range_t gain_range() const=0;
00173         virtual values_t gain_values() const=0;
00174         virtual range_t frequency_range() const=0;
00175         virtual range_t bandwidth_range() const=0;
00176         virtual values_t bandwidth_values() const=0;
00177 public:
00178         virtual num_name_map_t gain_modes() const=0;
00179         virtual bool calc_appropriate_gain_mode(int& mode)/* const*/=0;
00180         virtual bool auto_gain_mode() const=0;
00181 public:
00182         virtual const PARAMS& params() const=0;
00183         virtual demod* parent() const=0;
00184 };
00185 
00186 class RTL2832_API tuner_skeleton : public tuner
00187 {
00188 public:
00189         tuner_skeleton(demod* p);
00190         virtual ~tuner_skeleton();
00191 protected:
00192         demod* m_demod;
00193         tuner::PARAMS m_params;
00194         bool m_auto_gain_mode;
00195         int m_gain_mode;
00196         double m_freq;
00197         double m_gain;
00198         double m_bandwidth;
00199         range_t m_gain_range;
00200         values_t m_gain_values;
00201         range_t m_frequency_range;
00202         range_t m_bandwidth_range;
00203         values_t m_bandwidth_values;
00204         num_name_map_t m_gain_modes;
00205 public:
00206         virtual int initialise(tuner::PPARAMS params = NULL);
00207         virtual const char* name() const
00208         { return "(dummy)"; }
00209         virtual int set_frequency(double freq)
00210         { return SUCCESS; }
00211         virtual int set_bandwidth(double bw)
00212         { return SUCCESS; }
00213         virtual int set_gain(double gain)
00214         { return SUCCESS; }
00215         virtual int set_gain_mode(int mode)
00216         { return SUCCESS; }
00217 public:
00218         virtual int set_i2c_repeater(bool on = true, const char* function_name = NULL, int line_number = -1, const char* line = NULL);
00219         virtual int i2c_read(uint8_t i2c_addr, uint8_t *buffer, int len);
00220         virtual int i2c_write(uint8_t i2c_addr, uint8_t *buffer, int len);
00221         virtual int i2c_write_reg(uint8_t i2c_addr, uint8_t reg, uint8_t val);
00222         virtual int i2c_read_reg(uint8_t i2c_addr, uint8_t reg, uint8_t& data);
00223 public:
00224         virtual double frequency() const
00225         { return m_freq; }
00226         virtual double bandwidth() const
00227         { return m_bandwidth; }
00228         virtual double gain() const
00229         { return m_gain; }
00230         virtual int gain_mode() const
00231         { return m_gain_mode; }
00232         virtual int set_auto_gain_mode(bool on = true)
00233         { m_auto_gain_mode = on; return SUCCESS; }
00234 public:
00235         virtual range_t gain_range() const
00236         { return m_gain_range; }
00237         virtual values_t gain_values() const
00238         { return m_gain_values; }
00239         virtual range_t frequency_range() const
00240         { return m_frequency_range; }
00241         virtual range_t bandwidth_range() const
00242         { return m_bandwidth_range; }
00243         virtual values_t bandwidth_values() const
00244         { return m_bandwidth_values; }
00245 public:
00246         virtual num_name_map_t gain_modes() const
00247         { return m_gain_modes; }
00248         virtual bool calc_appropriate_gain_mode(int& mode)/* const*/
00249         { mode = m_gain_mode; return true; }
00250         virtual bool auto_gain_mode() const
00251         { return m_auto_gain_mode; }
00252 public:
00253         const tuner::PARAMS& params() const
00254         { return m_params; }
00255         demod* parent() const
00256         { return m_demod; }
00257 };
00258 
00259 class i2c_repeater_scope
00260 {
00261 private:
00262         i2c_interface* m_p;
00263         const char* m_function_name;
00264         int m_line_number;
00265         const char* m_line;
00266 public:
00267         i2c_repeater_scope(i2c_interface* p, const char* function_name = NULL, int line_number = -1, const char* line = NULL)
00268                 : m_p(p)
00269                 , m_function_name(function_name)
00270                 , m_line_number(line_number)
00271                 , m_line(line)
00272         { p->set_i2c_repeater(true, function_name, line_number, line); }
00273         ~i2c_repeater_scope()
00274         { m_p->set_i2c_repeater(false, m_function_name, m_line_number, m_line); }
00275 };
00276 
00277 #define I2C_REPEATER_SCOPE(p)           i2c_repeater_scope _i2c_repeater_scope(p, CURRENT_FUNCTION, __LINE__, p->name())
00278 #define THIS_I2C_REPEATER_SCOPE()       I2C_REPEATER_SCOPE(this)
00279 
00280 typedef struct device_info
00281 {
00282         const char* name;
00283         uint16_t vid, pid;
00284         tuner::CreateTunerFn factory;
00285         uint32_t max_rate, min_rate, crystal_frequency, flags;
00286 } DEVICE_INFO, *PDEVICE_INFO;
00287 
00288 //#define CHECK_LIBUSB_RESULT(r)                        (r)
00289 //#define CHECK_LIBUSB_NEG_RESULT(r)            (r)
00290 //#define CHECK_LIBUSB_RESULT_EX(r,f,l,s)       (r)
00291 #define CHECK_LIBUSB_RESULT(r)                          check_libusb_result(r, false, CURRENT_FUNCTION, __LINE__, #r)
00292 #define CHECK_LIBUSB_NEG_RESULT(r)                      check_libusb_result(r, true, CURRENT_FUNCTION, __LINE__, #r)
00293 #define CHECK_LIBUSB_RESULT_EX(r,f,l,s)         check_libusb_result(r, false, f, l, s)
00294 
00295 #define CHECK_LIBUSB_RESULT_RETURN_EX(d,r)      \
00296         { int res = d->CHECK_LIBUSB_RESULT(r); \
00297         if (res <= 0) return res; }
00298 
00299 #define CHECK_LIBUSB_NEG_RESULT_RETURN_EX(d,r)  \
00300         { int res = d->CHECK_LIBUSB_NEG_RESULT(r); \
00301         if (res < 0) return res; }
00302 
00303 #define CHECK_LIBUSB_RESULT_RETURN(r)           CHECK_LIBUSB_RESULT_RETURN_EX(this,r)
00304 #define CHECK_LIBUSB_NEG_RESULT_RETURN(d,r)     CHECK_LIBUSB_NEG_RESULT_RETURN_EX(this,r)
00305 
00306 #define RTL2832_FIR_COEFF_COUNT 20
00307 #define RTL2832_TUNER_NAME_LEN  (32+1)
00308 
00309 class RTL2832_API demod : public i2c_interface, public named_interface
00310 {
00311 public:
00312         demod();
00313         virtual ~demod();
00314 public:
00315         //static const int FIR_COEFF_COUNT      = 20;
00316         //static const int TUNER_NAME_LEN               = 32+1;
00317         typedef struct params
00318         {
00319                 uint16_t                vid;
00320                 uint16_t                pid;
00321                 bool                    verbose;
00322                 int                             default_timeout;        // 0: use default, -1: poll only
00323                 log_sink*               message_output;
00324                 bool                    use_custom_fir_coefficients;
00325                 uint8_t                 fir_coeff[RTL2832_FIR_COEFF_COUNT];
00326                 //bool                  use_tuner_params;       // Use if valid tuner::PPARAMS pointer
00327                 tuner::PPARAMS  tuner_params;
00328                 uint32_t                crystal_frequency;
00329                 char                    tuner_name[RTL2832_TUNER_NAME_LEN];
00330         } PARAMS, *PPARAMS;
00331 protected:
00332         struct libusb_device_handle *m_devh;
00333         PDEVICE_INFO m_current_info;
00334         tuner *m_tuner, *m_dummy_tuner;
00335         bool m_libusb_init_done;
00336         PARAMS m_params;
00337         range_t m_sample_rate_range;
00338         double m_sample_rate;
00339         uint32_t m_crystal_frequency;
00340         bool m_tuner_was_active;        // True if the kernel driver was detached
00341 public:
00342         int initialise(PPARAMS params = NULL);
00343         const char* name() const;
00344         void destroy();
00345         int reset();
00346         int set_sample_rate(uint32_t samp_rate, double* real_rate = NULL);
00347         int set_if(double frequency);
00348         int read_samples(unsigned char* buffer, uint32_t buffer_size, int* bytes_read, int timeout = -1);
00349 protected:
00350         int find_device();
00351         int init_demod();
00352         int demod_write_reg(uint8_t page, uint16_t addr, uint16_t val, uint8_t len);
00353         int demod_read_reg(uint8_t page, uint8_t addr, uint8_t len, uint16_t& reg);
00354         int write_reg(uint8_t block, uint16_t addr, uint16_t val, uint8_t len);
00355         int read_reg(uint8_t block, uint16_t addr, uint8_t len, uint16_t& reg);
00356         int write_array(uint8_t block, uint16_t addr, uint8_t *array, uint8_t len);
00357         int read_array(uint8_t block, uint16_t addr, uint8_t *array, uint8_t len);
00358 public:
00359         int check_libusb_result(int res, bool zero_okay, const char* function_name = NULL, int line_number = -1, const char* line = NULL);
00360         void log(const char* message, ...);
00361 public:
00362         int set_i2c_repeater(bool on = true, const char* function_name = NULL, int line_number = -1, const char* line = NULL);
00363         int i2c_read(uint8_t i2c_addr, uint8_t *buffer, int len);
00364         int i2c_write(uint8_t i2c_addr, uint8_t *buffer, int len);
00365         int i2c_write_reg(uint8_t i2c_addr, uint8_t reg, uint8_t val);
00366         int i2c_read_reg(uint8_t i2c_addr, uint8_t reg, uint8_t& data);
00367 public:
00368         int set_gpio_output(uint8_t gpio);
00369         int set_gpio_bit(uint8_t gpio, int val);
00370 public:
00371         inline tuner* active_tuner() const
00372         { return m_tuner; }
00373         inline double sample_rate() const
00374         { return m_sample_rate; }
00375         inline uint32_t crystal_frequency() const
00376         { return m_crystal_frequency; }
00377         range_t sample_rate_range() const
00378         { return m_sample_rate_range; }
00379 protected:
00380         enum usb_reg {
00381                 USB_SYSCTL                      = 0x2000,
00382                 USB_CTRL                        = 0x2010,
00383                 USB_STAT                        = 0x2014,
00384                 USB_EPA_CFG                     = 0x2144,
00385                 USB_EPA_CTL                     = 0x2148,
00386                 USB_EPA_MAXPKT          = 0x2158,
00387                 USB_EPA_MAXPKT_2        = 0x215a,
00388                 USB_EPA_FIFO_CFG        = 0x2160,
00389         };
00390         enum sys_reg {
00391                 DEMOD_CTL               = 0x3000,
00392                 GPO                             = 0x3001,
00393                 GPI                             = 0x3002,
00394                 GPOE                    = 0x3003,
00395                 GPD                             = 0x3004,
00396                 SYSINTE                 = 0x3005,
00397                 SYSINTS                 = 0x3006,
00398                 GP_CFG0                 = 0x3007,
00399                 GP_CFG1                 = 0x3008,
00400                 SYSINTE_1               = 0x3009,
00401                 SYSINTS_1               = 0x300a,
00402                 DEMOD_CTL_1             = 0x300b,
00403                 IR_SUSPEND              = 0x300c,
00404         };
00405         enum blocks {
00406                 DEMODB                  = 0,
00407                 USBB                    = 1,
00408                 SYSB                    = 2,
00409                 TUNB                    = 3,
00410                 ROMB                    = 4,
00411                 IRB                             = 5,
00412                 IICB                    = 6,
00413         };
00414 };
00415 
00416 }
00417 
00418 #endif // INCLUDED_RTL2832