def py_rtlsdr_close(self, dev_handle_ptr): """ Closes the existing device handle to a RTL-SDR device. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. Raises ------ * ValueError * If fails to close the device handle. """ if not self.__apis_init_stat['py_rtlsdr_close']: f = self.clib.rtlsdr_close f.restype, f.argtypes = c_int, [p_rtlsdr_dev] self.__apis_init_stat['py_rtlsdr_close'] = True self.__check_for_rtlsdr_devices() result = self.clib.rtlsdr_close(dev_handle_ptr) if result != 0: print_error_msg( "Failed to close device handle for device index: %d." % (device_index)) raise ValueError
def py_rtlsdr_get_sample_rate(self, device_handle_ptr): """ Get the current sample rate of the device in Hz. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. Raises ------ * ValueError * If fails to read the sample rate of the device. Returns ------- * sample_rate : (int) Returns the sample rate in Hz. """ if not self.__apis_init_stat['py_rtlsdr_get_sample_rate']: f = self.clib.rtlsdr_get_sample_rate f.restype, f.argtypes = c_uint32, [p_rtlsdr_dev] self.__apis_init_stat['py_rtlsdr_get_sample_rate'] = True self.__check_for_rtlsdr_devices() sample_rate = self.clib.rtlsdr_get_sample_rate(device_handle_ptr) if sample_rate == 0: print_error_msg("Failed to read the device sample rate.") raise ValueError return sample_rate
def py_rtlsdr_get_center_freq(self, device_handle_ptr): """ Reads and returns the center frequency of the tuner to which it is currently tuned to. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. Returns ------- * center_freq : (int) Returns center frequency to which device is tuned to in Hz. Raises ------ * ValueError * If fails to read the center freq. """ if not self.__apis_init_stat['py_rtlsdr_get_center_freq']: f = self.clib.rtlsdr_get_center_freq f.restype, f.argtypes = c_uint, [p_rtlsdr_dev] self.__apis_init_stat['py_rtlsdr_get_center_freq'] = True self.__check_for_rtlsdr_devices() center_freq = self.clib.rtlsdr_get_center_freq(device_handle_ptr) if center_freq == 0: print_error_msg( "Failed to read the center freq of the tuner. Make sure to set the center freq before querying it." ) raise ValueError return center_freq
def __check_for_rtlsdr_devices(self): """ Checks whether any RTL-SDR device is attached to the host. Raises ------ * ValueError : No device is found. """ if self.py_rtlsdr_get_device_count() == 0: print_error_msg("No RTL-SDR device is attached to the host.") raise ValueError
def enable_auto_tuner_gain(self, enable): if type(enable) != bool: print_error_msg("Expected bool. Got: %s" % (type(enable))) raise ValueError self.clib.py_rtlsdr_set_tuner_gain_mode(self.__dev_ptr, manual=not enable) self.__enable_auto_tuner_gain = enable if self.__logging_level == 1: if enable: print_success_msg("Tuner gain selection is set to auto.") else: print_success_msg("Tuner gain selection is set to manual.")
def py_rtlsdr_set_tuner_gain_mode(self, device_handle_ptr, manual=False): """ Sets the tuner gain mode to automatic or manual. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. * manual : (bool) Enable manual tuner gain mode. Default: False (auto) Raises ------ * ValueError * If fails to set the specified gain mode. * TypeError * If manual is not of bool type. """ if not self.__apis_init_stat['py_rtlsdr_set_tuner_gain_mode']: f = self.clib.rtlsdr_set_tuner_gain_mode f.restype, f.argtypes = c_int, [p_rtlsdr_dev, c_int] self.__apis_init_stat['py_rtlsdr_set_tuner_gain_mode'] = True self.__check_for_rtlsdr_devices() if bool(manual) != manual: print_error_msg("Expected manual to be of bool type. Got: %s", type(manual)) raise TypeError manual = bool(manual) if manual: enable_manual_mode = 1 else: enable_manual_mode = 0 result = self.clib.rtlsdr_set_tuner_gain_mode( device_handle_ptr, c_int(enable_manual_mode)) if result != 0: print_error_msg("Failed to set tuner mode to %d." % (enable_manual_mode)) raise ValueError """
def py_rtlsdr_get_xtal_freq(self, device_handle_ptr): """ Reads and returns the crystal frequency used to clock the RTL2832 and the Rafael Micro R820T tuner. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. Returns ------- * rtl_freq : (int) Returns RTL2832 crystal frequency in Hz. * tuner_freq : (int) Returns Tuner frequency in Hz. Raises ------ * ValueError * If fails to read the xtal freq of tuner or RTL2832 chip. """ if not self.__apis_init_stat['py_rtlsdr_get_xtal_freq']: f = self.clib.rtlsdr_get_xtal_freq f.restype, f.argtypes = c_int, [ p_rtlsdr_dev, POINTER(c_uint32), POINTER(c_uint32) ] self.__apis_init_stat['py_rtlsdr_get_xtal_freq'] = True self.__check_for_rtlsdr_devices() rtl_freq = c_uint32(0) tuner_freq = c_uint32(0) result = self.clib.rtlsdr_get_xtal_freq(device_handle_ptr, byref(rtl_freq), byref(tuner_freq)) if result != 0: print_error_msg( "Failed to fetch xtal freq. of tuner and RTL2832 chip.") raise ValueError return rtl_freq.value, tuner_freq.value
def py_rtlsdr_set_agc_mode(self, device_handle_ptr, enable=True): """ Enable or disable the intenal AGC of the RTL2832 chip. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. * enable : (bool) Enable automatic gain contorl (agc). Default: True (enabled) Raises ------ * ValueError * If fails to set the agc mode. * TypeError * If enable is not of bool type. """ if not self.__apis_init_stat['py_rtlsdr_set_agc_mode']: f = self.clib.rtlsdr_set_agc_mode f.restype, f.argtypes = c_int, [p_rtlsdr_dev, c_int] self.__apis_init_stat['py_rtlsdr_set_agc_mode'] = True self.__check_for_rtlsdr_devices() if bool(enable) != enable: print_error_msg("Expected enable to be of bool type. Got: %s", type(enable)) raise TypeError enable = bool(enable) if enable: enable_mode = 1 else: enable_mode = 0 result = self.clib.rtlsdr_set_agc_mode(device_handle_ptr, c_int(enable_mode)) if result != 0: print_error_msg("Failed to set internal agc mode to %d." % (enable_manual_mode)) raise ValueError """
def py_rtlsdr_get_tuner_gains(self, device_handle_ptr): """ Returns the list of supported gain values of the tuner. The values are returned in dB. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. Raises ------ * ValueError * If fails to the read the supported gain values. Returns ------- * gain_values : (list) List of supported gain values of the tuner in dB. """ if not self.__apis_init_stat['py_rtlsdr_get_tuner_gains']: f = self.clib.rtlsdr_get_tuner_gains f.restype, f.argtypes = c_int, [p_rtlsdr_dev, POINTER(c_int)] self.__apis_init_stat['py_rtlsdr_get_tuner_gains'] = True self.__check_for_rtlsdr_devices() c_gain_values_list = [-1] * 50 c_gain_values_list = (c_int * len(c_gain_values_list))(*c_gain_values_list) result = self.clib.rtlsdr_get_tuner_gains(device_handle_ptr, c_gain_values_list) if result <= 0: print_error_msg( "Failed to read supported gain values for the tuner.") raise ValueError gain_values = [] for idx in range(0, result): gain_values.append(c_gain_values_list[idx] / 10.0) return gain_values
def __init__(self, ): # Load librtlsdr library crtlsdr_shared_lib = 'rtlsdr.so' if find_library(crtlsdr_shared_lib) is None: print_error_msg( "Unable to find librtlsdr.so. Make sure to install it from https://osmocom.org/projects/rtl-sdr/wiki/Rtl-sdr." ) raise ValueError crtlsdr_shared_lib = find_library(crtlsdr_shared_lib) self.__clib = CDLL(crtlsdr_shared_lib) # API's init status self.__apis_init_stat = {} for api_name in dir(librtlsdr): if "py_rtlsdr" in api_name: self.__apis_init_stat[api_name] = False
def py_rtlsdr_get_index_by_serial(self, serial_id): """ Returns the device index with whose serial number is given by serial_id. Parameters ---------- * serial_id : (str) The serial id of the RTL-SDR device. Returns ------- * device_index : (int) Returns the device index of the RTL-SDR device with serial_id. Raises ------ * ValueError: * If serial_id is not string. * Warning: * If not device is found corresponding to device index. """ if not self.__apis_init_stat['py_rtlsdr_get_index_by_serial']: f = self.clib.rtlsdr_get_index_by_serial f.restype, f.argstypes = c_int, [POINTER(c_ubyte)] self.__apis_init_stat['py_rtlsdr_get_index_by_serial'] = True self.__check_for_rtlsdr_devices() if type(serial_id) != str: print_error_msg("Expected serial_id to be string. Got: %s" % (type(serial_id))) raise ValueError cserial_id = cstr(serial_id) result = self.clib.rtlsdr_get_index_by_serial(cserial_id) if (result < 0): print_warn_msg("Failed to fetch any device with serial id: %s" % (serial_id)) return None return result
def py_rtlsdr_set_sample_rate(self, device_handle_ptr, sample_rate): """ Sets the sample rate of the device. Valid sample rate range for R820 Tuner. 226 ksps - 3.2 msps. Recomended to keep sample rate <= 2.8 msps. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. * sample_rate : (int) Sample rate in Hz. Raises ------ * ValueError * If fails to set the sample rate of the device. * TypeError * If sample rate type/value is invalid. """ if not self.__apis_init_stat['py_rtlsdr_set_sample_rate']: f = self.clib.rtlsdr_set_sample_rate f.restype, f.argtypes = c_int, [p_rtlsdr_dev, c_uint32] self.__apis_init_stat['py_rtlsdr_set_sample_rate'] = True self.__check_for_rtlsdr_devices() if int(sample_rate) != sample_rate: print_error_msg("Expected sample_rate to be of type int. Got: %s" % (type(sample_rate))) raise ValueError sample_rate = int(sample_rate) result = self.clib.rtlsdr_set_sample_rate(device_handle_ptr, c_uint32(sample_rate)) if result != 0: print_error_msg("Failed to set the device sample rate to %d Hz." % (sample_rate)) raise ValueError
def py_rtlsdr_set_freq_correction(self, device_handle_ptr, ppm): """ Sets the frequency correction value. The value must in parts per million (ppm). Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. * ppm : (int) Frequency correction in ppm. Raises ------ * ValueError * If fails to set the frequency correction. * TypeError * If frequency correction value is invalid. """ if not self.__apis_init_stat['py_rtlsdr_set_freq_correction']: f = self.clib.rtlsdr_set_freq_correction f.restype, f.argtypes = c_int, [p_rtlsdr_dev, c_int] self.__apis_init_stat['py_rtlsdr_set_freq_correction'] = True self.__check_for_rtlsdr_devices() if int(ppm) != ppm: print_error_msg("Expected ppm to be of type int. Got: %s" % (type(ppm))) raise ValueError ppm = int(ppm) result = self.clib.rtlsdr_set_freq_correction(device_handle_ptr, c_int(ppm)) if result != 0: print_error_msg("Failed to do the freq correction by %d" % (ppm)) raise ValueError
def py_rtlsdr_reset_buffer(self, device_handle_ptr): """ Resets the RTL2832 sample buffer. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. Raises ------ * ValueError * If fails to reset the buffer. """ if not self.__apis_init_stat['py_rtlsdr_reset_buffer']: f = self.clib.rtlsdr_reset_buffer f.restype, f.argtypes = c_int, [p_rtlsdr_dev] self.__apis_init_stat['py_rtlsdr_reset_buffer'] = True self.__check_for_rtlsdr_devices() result = self.clib.rtlsdr_reset_buffer(device_handle_ptr) if result != 0: print_error_msg("Failed to reset the RTL2832 sample buffer.") raise ValueError
def py_rtlsdr_set_tuner_gain(self, device_handle_ptr, gain): """ Set the specified gain value of the tuner. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. * gain : (float) gain to apply in db. Raises ------ * ValueError * If fails to set the gain value. * TypeError * If invalid/unsupported gain value is specified. """ if not self.__apis_init_stat['py_rtlsdr_set_tuner_gain']: f = self.clib.rtlsdr_set_tuner_gain f.restype, f.argtypes = c_int, [p_rtlsdr_dev, c_int] self.__apis_init_stat['py_rtlsdr_set_tuner_gain'] = True self.__check_for_rtlsdr_devices() if float(gain) != gain: print_error_msg("Expected gain to be of type float. Got: %s", type(gain)) raise TypeError supported_gain_values = self.py_rtlsdr_get_tuner_gains( device_handle_ptr) if gain not in supported_gain_values: print_error_msg( "Invalid/Unsupported gain value %.1f dB is specified." % (gain)) raise TypeError c_gain_value = int(gain * 10.0) result = self.clib.rtlsdr_set_tuner_gain(device_handle_ptr, c_int(c_gain_value)) if result != 0: print_error_msg( "Failed to set the specified gain value %.1f dB of the tuner." % (gain)) raise ValueError
def py_rtlsdr_set_center_freq(self, device_handle_ptr, center_freq): """ Sets the center frequency of the tuner to the specified frequency. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. * center_freq : (int) Center frequency to tune device to in Hz. Raises ------ * ValueError * If fails to set the specified center freq. * If center freq is invalid. * TypeError * If type of center freq is not int. """ if not self.__apis_init_stat['py_rtlsdr_set_center_freq']: f = self.clib.rtlsdr_set_center_freq f.restype, f.argtypes = c_int, [p_rtlsdr_dev, c_uint32] self.__apis_init_stat['py_rtlsdr_set_center_freq'] = True self.__check_for_rtlsdr_devices() if int(center_freq) != center_freq: print_error_msg("Expected center freq to be int. Got: %s" % (type(center_freq))) raise TypeError center_freq = int(center_freq) if center_freq <= 0: print_error_msg("Expected center freq > 0. Got: %d" % (center_freq)) raise ValueError result = self.clib.rtlsdr_set_center_freq(device_handle_ptr, c_uint32(center_freq)) if result != 0: print_error_msg("Failed to set center freq to: %d Hz." % (center_freq)) raise ValueError
def py_rtlsdr_get_device_name(self, device_index=0): """ Returns the name of the connected device at given index. Parameters ---------- * device_index : (int) Device index. Raises ------ * ValueError * If device index is greater than the number of connected devices. * If device index is negative. """ if not self.__apis_init_stat['py_rtlsdr_get_device_name']: f = self.clib.rtlsdr_get_device_name f.restype, f.argstypes = POINTER(c_ubyte), [c_uint32] self.__apis_init_stat['py_rtlsdr_get_device_name'] = True self.__check_for_rtlsdr_devices() if int(device_index) != device_index: print_error_msg("Expected device index to be int. Got: %d" % (type(device_index))) raise ValueError device_index = int(device_index) if device_index < 0: print_error_msg("Device index must be non-negative.") raise ValueError if device_index >= self.py_rtlsdr_get_device_count(): print_error_msg( "Expected device index < %d. Got device index: %d." % (self.py_rtlsdr_get_device_count(), device_index)) raise ValueError device_name = self.clib.rtlsdr_get_device_name(c_uint32(device_index)) return c_ubyte_ptr_to_string(device_name, 126)
def __init__(self, device_index, logging_level=3): self.__librtlsdr = librtlsdr() if int(device_index) != device_index: print_error_msg("Expected device index to be of int. Got: %s." % (type(device_index))) raise TypeError device_index = int(device_index) self.__device_index = device_index if int(logging_level) != logging_level: print_error_msg("Expected logging level to be int. Got: %s" % (type(logging_level))) raise TypeError logging_level = int(logging_level) if logging_level < 1 or logging_level > 4: print_error_msg("Invalid logging level %d." % (logging_level)) raise ValueError # Setting the logging level. self.__logging_level = logging_level # Open a device pointer to the SDR. self.__dev_ptr = c_void_p(None) self.__dev_ptr = self.clib.py_rtlsdr_open(device_index) if self.__logging_level == 1: print_success_msg( "Successfully opened a libusb connection to the device.") # Get SDR details self.__mid, self.__vid, self.__serial = self.clib.py_rtlsdr_get_device_usb_strings( self.__device_index) if self.__logging_level < 3: device_strings = "Manufacturer: %s, Vendor ID: %s, Serial %s." % ( self.__mid, self.__vid, self.__serial) print_info_msg(device_strings) # Attributes self.__center_freq = None self.__sample_rate = None self.__enable_agc = None self.__tuner_gain = None self.__enable_auto_tuner_gain = None self.__tuner_gains = self.clib.py_rtlsdr_get_tuner_gains( self.__dev_ptr) self.__freq_correction = self.clib.py_rtlsdr_get_freq_correction( self.__dev_ptr) self.__rtl_xo_freq, self.__tuner_xo_freq = self.clib.py_rtlsdr_get_xtal_freq( self.__dev_ptr) self.__num_recv_samples = None # Init defaults self.__init_default() # Reset libusb buffer self.clib.py_rtlsdr_reset_buffer(self.__dev_ptr) if self.__logging_level < 3: device_config = 'Intialized device with following default values.' device_config += '\n\t1. Center Freq: %d Hz.' % (self.center_freq) device_config += '\n\t2. Sample Rate: %d MSPS.' % ( self.sample_rate) device_config += '\n\t3. AGC Enabled: %s.' % (self.enable_agc) device_config += '\n\t4. Automatic tuner gain selection: %s.' % ( self.enable_auto_tuner_gain) device_config += '\n\t5. Freq Correction: %d ppm' % ( self.freq_correction) device_config += '\n\t6. Tuner gain: %s dB' % (self.tuner_gain) device_config += '\n\t7. Frame size (samples/frame): %d' % ( self.num_recv_samples) print_info_msg(device_config)
def py_rtlsdr_get_device_usb_strings(self, device_index=0): """ Returns the USB device strings. Parameters ---------- * device_index : (int) Device index. Returns ------- * mid : (str) Device manufacturer. * pid : (str) Device product ID. * serial : (str) Device serial ID. Raises ------ * TypeError * If device index is negative. * If device index is greater than or equal to the number of connected supported devices. """ if not self.__apis_init_stat['py_rtlsdr_get_device_usb_strings']: f = self.clib.rtlsdr_get_device_usb_strings f.restype, f.argstypes = c_int, [ c_uint32, POINTER(c_ubyte), POINTER(c_ubyte), POINTER(c_ubyte) ] self.__apis_init_stat['py_rtlsdr_get_device_usb_strings'] = True self.__check_for_rtlsdr_devices() if int(device_index) != device_index: print_error_msg("Expected device index to be int. Got: %d" % (type(device_index))) raise ValueError device_index = int(device_index) if device_index < 0: print_error_msg("Device index must be non-negative.") raise ValueError if device_index >= self.py_rtlsdr_get_device_count(): print_error_msg( "Expected device index < %d. Got device index: %d." % (self.py_rtlsdr_get_device_count(), device_index)) raise ValueError mid = (c_ubyte * 256)() pid = (c_ubyte * 256)() serial = (c_ubyte * 256)() result = self.clib.rtlsdr_get_device_usb_strings( c_uint32(device_index), mid, pid, serial) if (result != 0): print_error_msg( "Failed tp fetch USB device strings for device indexed as %d." % (device_index)) raise ValueError return c_ubyte_ptr_to_string(mid, 256), c_ubyte_ptr_to_string( pid, 256), c_ubyte_ptr_to_string(serial, 256)
def py_rtlsdr_open(self, device_index): """ Create and return the device handle for the RTL-SDR for given device index. Parameters ---------- * device_index : (int) RTL-SDR device index. Raises ------ * ValueError * If invalid device index is passed. * If fail to open the device handle. Returns ------- * handle : (p_rtlsdr_dev) Device handle. """ if not self.__apis_init_stat['py_rtlsdr_open']: f = self.clib.rtlsdr_open f.restype, f.argtypes = c_int, [POINTER(p_rtlsdr_dev), c_uint] self.__apis_init_stat['py_rtlsdr_open'] = True self.__check_for_rtlsdr_devices() if int(device_index) != device_index: print_error_msg("Expected device index to be int. Got: %d" % (type(device_index))) raise ValueError device_index = int(device_index) if device_index < 0: print_error_msg("Device index must be non-negative.") raise ValueError if device_index >= self.py_rtlsdr_get_device_count(): print_error_msg( "Expected device index < %d. Got device index: %d." % (self.py_rtlsdr_get_device_count(), device_index)) raise ValueError dev_p = p_rtlsdr_dev(None) c_device_index = c_uint(device_index) result = self.clib.rtlsdr_open(dev_p, c_uint(device_index)) if result == -1: print_error_msg("Device or libusb is inaccessible.") raise ValueError if result == -3: print_error_msg( "Device permissions don't fit. Check if dev rules file is installed." ) if (result < 0): print_error_msg( "Failed to open device handle for device index: %d." % (device_index.value)) raise ValueError return dev_p
def py_rtlsdr_read_sync(self, device_handle_ptr, samples_to_read): """ Reads and returns the IQ samples from the deivce synchronously. Each sample is 16 bits. First 8 bits denote I and next 8 bits denotes Q sample. Parameters ---------- * dev_handle_ptr : (p_rtlsdr_dev) Device handle pointer. * samples_to_read : (int) Number of samples to read from the device. Raises ------ * ValueError * If fails to read from specified device. * TypeError * If type/value of samples_to_read is invalid. * Warning * If fails to read the requested number of samples. Returns ------- * read_time : (float) Time taken to read the requested number of samples. * raw_samples : (np.array) List of raw samples read from the device. """ if not self.__apis_init_stat['py_rtlsdr_read_sync']: f = self.clib.rtlsdr_read_sync f.restype, f.argtypes = c_int, [ p_rtlsdr_dev, c_void_p, c_int, POINTER(c_int) ] self.__apis_init_stat['py_rtlsdr_read_sync'] = True self.__check_for_rtlsdr_devices() if int(samples_to_read) != samples_to_read: print_error_msg("Expected samples_to_read of type int. Got: %s" % (type(samples_to_read))) raise TypeError samples_to_read = int(samples_to_read) if samples_to_read <= 0: print_error_msg( "Number of samples to read from device should be atleast one. Got: %d" % (samples_to_read)) raise ValueError num_bytes = 2 * samples_to_read sample_bfr = (c_ubyte * num_bytes)() num_bytes_read = c_int(-1) start_time = datetime.datetime.now() result = self.clib.rtlsdr_read_sync(device_handle_ptr, sample_bfr, c_int(num_bytes), num_bytes_read) end_time = datetime.datetime.now() if (result != 0): print_error_msg( "Failed to read samples from device due to some libusb error.") raise ValueError if num_bytes != num_bytes_read.value: print_warn_msg( "Requested to read %d bytes. Read %d bytes from the device." % (num_bytes, num_bytes_read.value)) return (end_time - start_time ).total_seconds() * 1000, np.ctypeslib.as_array(sample_bfr)
def num_recv_samples(self, num_samples): if type(num_samples) != int: print_error_msg("Expected int. Got: %s" % (type(num_samples))) raise ValueError self.__num_recv_samples = num_samples