Class: RTLSDR::Device

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/rtlsdr/device.rb

Overview

High-level interface to RTL-SDR devices

The Device class provides a Ruby-idiomatic interface to RTL-SDR dongles, wrapping the low-level librtlsdr C API with convenient methods and automatic resource management. It supports both synchronous and asynchronous sample reading, comprehensive device configuration, and implements Enumerable for streaming operations.

Features:

  • Automatic device lifecycle management (open/close)
  • Frequency, gain, and sample rate control with validation
  • Multiple gain modes (manual, automatic, AGC)
  • Synchronous and asynchronous sample reading
  • IQ sample conversion to Ruby Complex numbers
  • EEPROM access and bias tee control
  • Enumerable interface for continuous streaming
  • Comprehensive error handling with custom exceptions

Examples:

Basic device setup

device = RTLSDR::Device.new(0)
device.configure(
  frequency: 100_000_000,    # 100 MHz
  sample_rate: 2_048_000,    # 2.048 MSPS
  gain: 496                   # 49.6 dB
)

Streaming samples

device.each(samples_per_read: 1024) do |samples|
  power = RTLSDR::DSP.average_power(samples)
  puts "Average power: #{power}"
end

Asynchronous reading

device.read_samples_async do |samples|
  # Process samples in real-time
  spectrum = RTLSDR::DSP.power_spectrum(samples)
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(index = 0) ⇒ Device

Create a new RTL-SDR device instance

Opens the specified RTL-SDR device and prepares it for use. The device will be automatically opened during initialization.

Examples:

Create device instance

device = RTLSDR::Device.new(0)
puts "Opened: #{device.name}"

Parameters:

  • index (Integer) (defaults to: 0)

    Device index to open (default: 0)

Raises:



62
63
64
65
66
67
68
69
# File 'lib/rtlsdr/device.rb', line 62

def initialize(index = 0)
  @index = index
  @handle = nil
  @streaming = false
  @async_thread = nil
  @buffer_reset_done = false
  open_device
end

Instance Attribute Details

#handleFFI::Pointer (readonly)

Returns Internal device handle pointer.

Returns:

  • (FFI::Pointer)

    Internal device handle pointer



49
50
51
# File 'lib/rtlsdr/device.rb', line 49

def handle
  @handle
end

#indexInteger (readonly)

Returns Device index (0-based).

Returns:

  • (Integer)

    Device index (0-based)



47
48
49
# File 'lib/rtlsdr/device.rb', line 47

def index
  @index
end

Instance Method Details

#agc_mode!Boolean

Enable automatic gain control

Returns:

  • (Boolean)

    true



336
337
338
# File 'lib/rtlsdr/device.rb', line 336

def agc_mode!
  self.agc_mode = true
end

#agc_mode=(enabled) ⇒ Object

Set automatic gain control mode

Parameters:

  • enabled (Boolean)

    true to enable AGC, false to disable



327
328
329
330
331
# File 'lib/rtlsdr/device.rb', line 327

def agc_mode=(enabled)
  mode = enabled ? 1 : 0
  result = FFI.rtlsdr_set_agc_mode(@handle, mode)
  check_result(result, "Failed to set AGC mode")
end

#auto_gain_mode!Boolean

Enable automatic gain mode

Returns:

  • (Boolean)

    false



267
268
269
# File 'lib/rtlsdr/device.rb', line 267

def auto_gain_mode!
  self.tuner_gain_mode = false
end

#bias_tee!Boolean

Enable bias tee

Returns:

  • (Boolean)

    true



402
403
404
# File 'lib/rtlsdr/device.rb', line 402

def bias_tee!
  enable_bias_tee
end

#bias_tee=(enabled) ⇒ Object

Bias tee control



385
386
387
388
389
# File 'lib/rtlsdr/device.rb', line 385

def bias_tee=(enabled)
  mode = enabled ? 1 : 0
  result = FFI.rtlsdr_set_bias_tee(@handle, mode)
  check_result(result, "Failed to set bias tee")
end

#cancel_asyncvoid

This method returns an undefined value.

Cancel asynchronous reading operation

Stops any active asynchronous reading and cleans up resources. This method is safe to call from within async callbacks.



578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
# File 'lib/rtlsdr/device.rb', line 578

def cancel_async
  return unless streaming?

  result = FFI.rtlsdr_cancel_async(@handle)
  @streaming = false

  # Only join if we're not calling from within the async thread itself
  if @async_thread && @async_thread != Thread.current
    @async_thread.join(1) # Wait up to 1 second for thread to finish
  end

  @async_thread = nil
  @async_callback = nil

  check_result(result, "Failed to cancel async operation")
end

#center_freqInteger Also known as: frequency

Get the current center frequency

Returns:

  • (Integer)

    Center frequency in Hz



162
163
164
# File 'lib/rtlsdr/device.rb', line 162

def center_freq
  FFI.rtlsdr_get_center_freq(@handle)
end

#center_freq=(freq) ⇒ Object Also known as: frequency=

Frequency control



154
155
156
157
# File 'lib/rtlsdr/device.rb', line 154

def center_freq=(freq)
  result = FFI.rtlsdr_set_center_freq(@handle, freq)
  check_result(result, "Failed to set center frequency")
end

#closevoid

This method returns an undefined value.

Close the RTL-SDR device

Closes the device handle and releases system resources. If async reading is active, it will be cancelled first. After closing, the device cannot be used until reopened.

Examples:

Close device

device.close
puts "Device closed"


86
87
88
89
90
91
92
93
# File 'lib/rtlsdr/device.rb', line 86

def close
  return unless open?

  cancel_async if streaming?
  result = FFI.rtlsdr_close(@handle)
  @handle = nil
  check_result(result, "Failed to close device")
end

#closed?Boolean

Check if the device is closed

Returns:

  • (Boolean)

    true if device is closed, false if open



98
99
100
# File 'lib/rtlsdr/device.rb', line 98

def closed?
  !open?
end

#configure(frequency: nil, sample_rate: nil, gain: nil, **options) ⇒ Object

Configuration shortcuts



610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
# File 'lib/rtlsdr/device.rb', line 610

def configure(frequency: nil, sample_rate: nil, gain: nil, **options)
  self.center_freq = frequency if frequency
  self.sample_rate = sample_rate if sample_rate

  if gain
    manual_gain_mode!
    self.tuner_gain = gain
  end

  options.each do |key, value|
    case key
    when :freq_correction then self.freq_correction = value
    when :bandwidth then self.tuner_bandwidth = value
    when :agc_mode then self.agc_mode = value
    when :test_mode then self.test_mode = value
    when :bias_tee then self.bias_tee = value
    when :direct_sampling then self.direct_sampling = value
    when :offset_tuning then self.offset_tuning = value
    end
  end

  self
end

#direct_samplingInteger?

Get current direct sampling mode

Returns:

  • (Integer, nil)

    Direct sampling mode or nil on error



351
352
353
354
355
356
# File 'lib/rtlsdr/device.rb', line 351

def direct_sampling
  result = FFI.rtlsdr_get_direct_sampling(@handle)
  return nil if result.negative?

  result
end

#direct_sampling=(mode) ⇒ Object

Set direct sampling mode

Parameters:

  • mode (Integer)

    Direct sampling mode (0=off, 1=I-ADC, 2=Q-ADC)



343
344
345
346
# File 'lib/rtlsdr/device.rb', line 343

def direct_sampling=(mode)
  result = FFI.rtlsdr_set_direct_sampling(@handle, mode)
  check_result(result, "Failed to set direct sampling")
end

#disable_bias_teeObject



395
396
397
# File 'lib/rtlsdr/device.rb', line 395

def disable_bias_tee
  self.bias_tee = false
end

#dump_eepromString

Read the entire EEPROM contents

Reads the complete 256-byte EEPROM data from the device and returns it as a binary string suitable for writing to a file.

Examples:

Dump EEPROM to file

File.binwrite("eeprom_backup.bin", device.dump_eeprom)

Returns:

  • (String)

    Binary string containing the entire EEPROM contents



447
448
449
450
# File 'lib/rtlsdr/device.rb', line 447

def dump_eeprom
  data = read_eeprom(0, 256) # RTL-SDR devices have a 256-byte EEPROM
  data.pack("C*") # Convert byte array to binary string
end

#each(samples_per_read: 1024) ⇒ Object

Enumerable interface for reading samples



596
597
598
599
600
601
602
603
604
605
606
607
# File 'lib/rtlsdr/device.rb', line 596

def each(samples_per_read: 1024)
  return enum_for(:each, samples_per_read: samples_per_read) unless block_given?

  loop do
    samples = read_samples(samples_per_read)
    yield samples
  rescue StandardError => e
    break if e.is_a?(Interrupt)

    raise
  end
end

#enable_bias_teeObject



391
392
393
# File 'lib/rtlsdr/device.rb', line 391

def enable_bias_tee
  self.bias_tee = true
end

#freq_correctionInteger

Get current frequency correction

Returns:

  • (Integer)

    Frequency correction in PPM



186
187
188
# File 'lib/rtlsdr/device.rb', line 186

def freq_correction
  FFI.rtlsdr_get_freq_correction(@handle)
end

#freq_correction=(ppm) ⇒ Object

Set frequency correction in PPM

Examples:

Set 15 PPM correction

device.freq_correction = 15

Parameters:

  • ppm (Integer)

    Frequency correction in parts per million



178
179
180
181
# File 'lib/rtlsdr/device.rb', line 178

def freq_correction=(ppm)
  result = FFI.rtlsdr_set_freq_correction(@handle, ppm)
  check_result(result, "Failed to set frequency correction")
end

#infoObject

Device info as hash



635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
# File 'lib/rtlsdr/device.rb', line 635

def info
  {
    index: @index,
    name: name,
    usb_strings: usb_strings,
    tuner_type: tuner_type,
    tuner_name: tuner_name,
    center_freq: center_freq,
    sample_rate: sample_rate,
    tuner_gain: tuner_gain,
    tuner_gains: tuner_gains,
    freq_correction: freq_correction,
    direct_sampling: direct_sampling,
    offset_tuning: offset_tuning
  }
end

#inspectString

Return string representation of device

Returns:

  • (String)

    Human-readable device information



655
656
657
658
659
660
661
# File 'lib/rtlsdr/device.rb', line 655

def inspect
  if open?
    "#<RTLSDR::Device:#{object_id.to_s(16)} index=#{@index} name=\"#{name}\" tuner=\"#{tuner_name}\" freq=#{center_freq}Hz rate=#{sample_rate}Hz>" # rubocop:disable Layout/LineLength
  else
    "#<RTLSDR::Device:#{object_id.to_s(16)} index=#{@index} closed>"
  end
end

#manual_gain_mode!Boolean

Enable manual gain mode

Returns:

  • (Boolean)

    true



260
261
262
# File 'lib/rtlsdr/device.rb', line 260

def manual_gain_mode!
  self.tuner_gain_mode = true
end

#nameObject

Device information



103
104
105
# File 'lib/rtlsdr/device.rb', line 103

def name
  RTLSDR.device_name(@index)
end

#offset_tuningBoolean?

Get current offset tuning mode

Returns:

  • (Boolean, nil)

    true if enabled, false if disabled, nil on error



370
371
372
373
374
375
# File 'lib/rtlsdr/device.rb', line 370

def offset_tuning
  result = FFI.rtlsdr_get_offset_tuning(@handle)
  return nil if result.negative?

  result == 1
end

#offset_tuning!Boolean

Enable offset tuning

Returns:

  • (Boolean)

    true



380
381
382
# File 'lib/rtlsdr/device.rb', line 380

def offset_tuning!
  self.offset_tuning = true
end

#offset_tuning=(enabled) ⇒ Object

Set offset tuning mode

Parameters:

  • enabled (Boolean)

    true to enable offset tuning, false to disable



361
362
363
364
365
# File 'lib/rtlsdr/device.rb', line 361

def offset_tuning=(enabled)
  mode = enabled ? 1 : 0
  result = FFI.rtlsdr_set_offset_tuning(@handle, mode)
  check_result(result, "Failed to set offset tuning")
end

#open?Boolean

Device lifecycle

Returns:

  • (Boolean)


72
73
74
# File 'lib/rtlsdr/device.rb', line 72

def open?
  !@handle.nil?
end

#read_async(buffer_count: 15, buffer_length: 262_144) {|Array<Integer>| ... } ⇒ Thread

Read raw IQ data asynchronously

Starts asynchronous reading of raw 8-bit IQ data. The provided block will be called for each buffer of data received.

Parameters:

  • buffer_count (Integer) (defaults to: 15)

    Number of buffers to use (default: 15)

  • buffer_length (Integer) (defaults to: 262_144)

    Length of each buffer in bytes (default: 262144)

Yields:

  • (Array<Integer>)

    Block called with each buffer of raw IQ data

Returns:

  • (Thread)

    Thread object running the async operation

Raises:



523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
# File 'lib/rtlsdr/device.rb', line 523

def read_async(buffer_count: 15, buffer_length: 262_144, &block)
  raise ArgumentError, "Block required for async reading" unless block_given?
  raise OperationFailedError, "Already streaming" if streaming?

  @streaming = true
  @async_callback = proc do |buf_ptr, len, _ctx|
    data = buf_ptr.read_array_of_uint8(len)
    block.call(data)
  rescue StandardError => e
    puts "Error in async callback: #{e.message}"
    cancel_async
  end

  @async_thread = Thread.new do
    result = FFI.rtlsdr_read_async(@handle, @async_callback, nil, buffer_count, buffer_length)
    @streaming = false
    # Don't raise error for cancellation (-1) or timeout (-5)
    check_result(result, "Async read failed") unless [-1, -5].include?(result)
  end

  @async_thread
end

#read_eeprom(offset, length) ⇒ Object

EEPROM access



419
420
421
422
423
424
# File 'lib/rtlsdr/device.rb', line 419

def read_eeprom(offset, length)
  data_ptr = ::FFI::MemoryPointer.new(:uint8, length)
  result = FFI.rtlsdr_read_eeprom(@handle, data_ptr, offset, length)
  check_result(result, "Failed to read EEPROM")
  data_ptr.read_array_of_uint8(length)
end

#read_samples(count = 1024) ⇒ Array<Complex>

Read complex samples synchronously

Reads the specified number of complex samples from the device and converts them from raw 8-bit IQ data to Ruby Complex numbers.

Examples:

Read 2048 samples

samples = device.read_samples(2048)
puts "Read #{samples.length} samples"

Parameters:

  • count (Integer) (defaults to: 1024)

    Number of complex samples to read (default: 1024)

Returns:

  • (Array<Complex>)

    Array of complex samples



490
491
492
493
494
495
496
497
498
499
500
501
502
503
# File 'lib/rtlsdr/device.rb', line 490

def read_samples(count = 1024)
  # RTL-SDR outputs 8-bit I/Q samples, so we need 2 bytes per complex sample
  data = read_sync(count * 2)

  # Convert to complex numbers (I + jQ)
  samples = []
  (0...data.length).step(2) do |i|
    i_sample = (data[i] - 128) / 128.0      # Convert to -1.0 to 1.0 range
    q_sample = (data[i + 1] - 128) / 128.0  # Convert to -1.0 to 1.0 range
    samples << Complex(i_sample, q_sample)
  end

  samples
end

#read_samples_async(buffer_count: 15, buffer_length: 262_144) {|Array<Complex>| ... } ⇒ Thread

Read complex samples asynchronously

Starts asynchronous reading and converts raw IQ data to complex samples. The provided block will be called for each buffer of complex samples.

Parameters:

  • buffer_count (Integer) (defaults to: 15)

    Number of buffers to use (default: 15)

  • buffer_length (Integer) (defaults to: 262_144)

    Length of each buffer in bytes (default: 262144)

Yields:

  • (Array<Complex>)

    Block called with each buffer of complex samples

Returns:

  • (Thread)

    Thread object running the async operation

Raises:

  • (ArgumentError)

    if no block is provided



556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
# File 'lib/rtlsdr/device.rb', line 556

def read_samples_async(buffer_count: 15, buffer_length: 262_144, &block)
  raise ArgumentError, "Block required for async reading" unless block_given?

  read_async(buffer_count: buffer_count, buffer_length: buffer_length) do |data|
    # Convert to complex samples
    samples = []
    (0...data.length).step(2) do |i|
      i_sample = (data[i] - 128) / 128.0
      q_sample = (data[i + 1] - 128) / 128.0
      samples << Complex(i_sample, q_sample)
    end

    block.call(samples)
  end
end

#read_sync(length) ⇒ Array<Integer>

Read raw IQ data synchronously

Reads raw 8-bit IQ data from the device. The buffer is automatically reset on the first read to avoid stale data.

Parameters:

  • length (Integer)

    Number of bytes to read

Returns:

  • (Array<Integer>)

    Array of 8-bit unsigned integers



465
466
467
468
469
470
471
472
473
474
475
476
477
478
# File 'lib/rtlsdr/device.rb', line 465

def read_sync(length)
  # Reset buffer before first read to avoid stale data
  reset_buffer unless @buffer_reset_done
  @buffer_reset_done = true

  buffer = ::FFI::MemoryPointer.new(:uint8, length)
  n_read_ptr = ::FFI::MemoryPointer.new(:int)

  result = FFI.rtlsdr_read_sync(@handle, buffer, length, n_read_ptr)
  check_result(result, "Failed to read synchronously")

  n_read = n_read_ptr.read_int
  buffer.read_array_of_uint8(n_read)
end

#reset_bufferObject

Streaming control



453
454
455
456
# File 'lib/rtlsdr/device.rb', line 453

def reset_buffer
  result = FFI.rtlsdr_reset_buffer(@handle)
  check_result(result, "Failed to reset buffer")
end

#sample_rateInteger Also known as: samp_rate

Get current sample rate

Returns:

  • (Integer)

    Sample rate in Hz



299
300
301
# File 'lib/rtlsdr/device.rb', line 299

def sample_rate
  FFI.rtlsdr_get_sample_rate(@handle)
end

#sample_rate=(rate) ⇒ Object Also known as: samp_rate=

Sample rate control



291
292
293
294
# File 'lib/rtlsdr/device.rb', line 291

def sample_rate=(rate)
  result = FFI.rtlsdr_set_sample_rate(@handle, rate)
  check_result(result, "Failed to set sample rate")
end

#set_bias_tee_gpio(gpio, enabled) ⇒ Boolean

Set bias tee GPIO state

Parameters:

  • gpio (Integer)

    GPIO pin number

  • enabled (Boolean)

    true to enable, false to disable

Returns:

  • (Boolean)

    The enabled state that was set



411
412
413
414
415
416
# File 'lib/rtlsdr/device.rb', line 411

def set_bias_tee_gpio(gpio, enabled)
  mode = enabled ? 1 : 0
  result = FFI.rtlsdr_set_bias_tee_gpio(@handle, gpio, mode)
  check_result(result, "Failed to set bias tee GPIO")
  enabled
end

#set_tuner_if_gain(stage, gain) ⇒ Integer

Set IF gain for specific stage

Parameters:

  • stage (Integer)

    IF stage number

  • gain (Integer)

    Gain value in tenths of dB

Returns:

  • (Integer)

    The gain value that was set



276
277
278
279
280
# File 'lib/rtlsdr/device.rb', line 276

def set_tuner_if_gain(stage, gain)
  result = FFI.rtlsdr_set_tuner_if_gain(@handle, stage, gain)
  check_result(result, "Failed to set IF gain")
  gain
end

#set_xtal_freq(rtl_freq, tuner_freq) ⇒ Object

Crystal oscillator frequencies



191
192
193
194
195
# File 'lib/rtlsdr/device.rb', line 191

def set_xtal_freq(rtl_freq, tuner_freq)
  result = FFI.rtlsdr_set_xtal_freq(@handle, rtl_freq, tuner_freq)
  check_result(result, "Failed to set crystal frequencies")
  [rtl_freq, tuner_freq]
end

#streaming?Boolean

Check if asynchronous streaming is active

Returns:

  • (Boolean)

    true if streaming, false otherwise



508
509
510
# File 'lib/rtlsdr/device.rb', line 508

def streaming?
  @streaming
end

#test_mode!Boolean

Enable test mode

Returns:

  • (Boolean)

    true



320
321
322
# File 'lib/rtlsdr/device.rb', line 320

def test_mode!
  self.test_mode = true
end

#test_mode=(enabled) ⇒ Object

Mode control



311
312
313
314
315
# File 'lib/rtlsdr/device.rb', line 311

def test_mode=(enabled)
  mode = enabled ? 1 : 0
  result = FFI.rtlsdr_set_testmode(@handle, mode)
  check_result(result, "Failed to set test mode")
end

#tuner_bandwidth=(bw) ⇒ Object

Set tuner bandwidth

Parameters:

  • bw (Integer)

    Bandwidth in Hz



285
286
287
288
# File 'lib/rtlsdr/device.rb', line 285

def tuner_bandwidth=(bw)
  result = FFI.rtlsdr_set_tuner_bandwidth(@handle, bw)
  check_result(result, "Failed to set bandwidth")
end

#tuner_gainInteger Also known as: gain

Get current tuner gain

Returns:

  • (Integer)

    Current gain in tenths of dB



237
238
239
# File 'lib/rtlsdr/device.rb', line 237

def tuner_gain
  FFI.rtlsdr_get_tuner_gain(@handle)
end

#tuner_gain=(gain) ⇒ Object Also known as: gain=

Set tuner gain in tenths of dB

Examples:

Set 40 dB gain

device.tuner_gain = 400

Parameters:

  • gain (Integer)

    Gain in tenths of dB (e.g., 496 = 49.6 dB)



229
230
231
232
# File 'lib/rtlsdr/device.rb', line 229

def tuner_gain=(gain)
  result = FFI.rtlsdr_set_tuner_gain(@handle, gain)
  check_result(result, "Failed to set tuner gain")
end

#tuner_gain_mode=(manual) ⇒ Object

Set gain mode (manual or automatic)

Parameters:

  • manual (Boolean)

    true for manual gain mode, false for automatic



251
252
253
254
255
# File 'lib/rtlsdr/device.rb', line 251

def tuner_gain_mode=(manual)
  mode = manual ? 1 : 0
  result = FFI.rtlsdr_set_tuner_gain_mode(@handle, mode)
  check_result(result, "Failed to set gain mode")
end

#tuner_gainsObject

Gain control



211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/rtlsdr/device.rb', line 211

def tuner_gains
  # First call to get count
  count = FFI.rtlsdr_get_tuner_gains(@handle, nil)
  return [] if count <= 0

  # Second call to get actual gains
  gains_ptr = ::FFI::MemoryPointer.new(:int, count)
  result = FFI.rtlsdr_get_tuner_gains(@handle, gains_ptr)
  return [] if result <= 0

  gains_ptr.read_array_of_int(result)
end

#tuner_nameString

Get human-readable tuner name

Examples:

Get tuner information

puts "Tuner: #{device.tuner_name}"

Returns:

  • (String)

    Tuner chip name and manufacturer



149
150
151
# File 'lib/rtlsdr/device.rb', line 149

def tuner_name
  FFI.tuner_type_name(tuner_type)
end

#tuner_typeInteger

Get the tuner type constant

Returns the tuner type as one of the RTLSDR_TUNER_* constants. The result is cached after the first call.

Returns:

  • (Integer)

    Tuner type constant

See Also:

  • FFI::RTLSDR_TUNER_*


140
141
142
# File 'lib/rtlsdr/device.rb', line 140

def tuner_type
  @tuner_type ||= FFI.rtlsdr_get_tuner_type(@handle)
end

#usb_stringsHash

Get USB device strings

Retrieves the USB manufacturer, product, and serial number strings for this device. Results are cached after the first call.

Examples:

Get USB information

usb_info = device.usb_strings
puts "#{usb_info[:manufacturer]} #{usb_info[:product]}"

Returns:

  • (Hash)

    Hash with :manufacturer, :product, :serial keys



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rtlsdr/device.rb', line 116

def usb_strings
  return @usb_strings if @usb_strings

  manufact = " " * 256
  product = " " * 256
  serial = " " * 256

  result = FFI.rtlsdr_get_usb_strings(@handle, manufact, product, serial)
  check_result(result, "Failed to get USB strings")

  @usb_strings = {
    manufacturer: manufact.strip,
    product: product.strip,
    serial: serial.strip
  }
end

#write_eeprom(data, offset) ⇒ Integer

Write data to EEPROM

Parameters:

  • data (Array<Integer>)

    Array of bytes to write

  • offset (Integer)

    EEPROM offset address

Returns:

  • (Integer)

    Number of bytes written



431
432
433
434
435
436
437
# File 'lib/rtlsdr/device.rb', line 431

def write_eeprom(data, offset)
  data_ptr = ::FFI::MemoryPointer.new(:uint8, data.length)
  data_ptr.write_array_of_uint8(data)
  result = FFI.rtlsdr_write_eeprom(@handle, data_ptr, offset, data.length)
  check_result(result, "Failed to write EEPROM")
  data.length
end

#xtal_freqArray<Integer>

Get crystal oscillator frequencies

Returns:

  • (Array<Integer>)

    Array of [rtl_freq, tuner_freq] in Hz



200
201
202
203
204
205
206
207
208
# File 'lib/rtlsdr/device.rb', line 200

def xtal_freq
  rtl_freq_ptr = ::FFI::MemoryPointer.new(:uint32)
  tuner_freq_ptr = ::FFI::MemoryPointer.new(:uint32)

  result = FFI.rtlsdr_get_xtal_freq(@handle, rtl_freq_ptr, tuner_freq_ptr)
  check_result(result, "Failed to get crystal frequencies")

  [rtl_freq_ptr.read_uint32, tuner_freq_ptr.read_uint32]
end