Module: Radio::Filter::Iq
- Defined in:
- lib/radio/filters/iq.rb
Defined Under Namespace
Modules: Complex
Instance Method Summary collapse
- #adjust!(data, phase, gain) ⇒ Object
-
#analyze ⇒ Object
Once per call, we will do an FFT to either start a new round of guessing or try again on the current set.
-
#collect(data) ⇒ Object
This maintains a buffer of recent data that we can grab for analysis.
- #detect_energies(spectrum) ⇒ Object
-
#rand_direction ⇒ Object
this is the IQ detection idea from the sdr# project.
- #remove_dc_bias!(data) ⇒ Object
- #setup ⇒ Object
Instance Method Details
#adjust!(data, phase, gain) ⇒ Object
106 107 108 109 110 |
# File 'lib/radio/filters/iq.rb', line 106 def adjust! data, phase, gain data.collect! do |v| Complex(v.real + phase * v.imag, v.imag * gain) end end |
#analyze ⇒ Object
Once per call, we will do an FFT to either start a new round of guessing or try again on the current set.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/radio/filters/iq.rb', line 70 def analyze return unless @cur_fft or @next_fft if !@cur_fft_count or @cur_fft_count > @tries @cur_fft = @next_fft @cur_fft_count = 0 fft = @cur_fft.dup adjust! fft, @phase, @gain @cur_fft_best = detect_energies FFTW3::fft(fft) else @cur_fft_count += 1 phaseIncrement = @iq_rate * rand_direction gainIncrement = @iq_rate * rand_direction fft = @cur_fft.dup adjust! fft, @phase + phaseIncrement, @gain + gainIncrement det = detect_energies FFTW3::fft(fft) if det > @cur_fft_best @cur_fft_best = det @gain += gainIncrement @phase += phaseIncrement end end end |
#collect(data) ⇒ Object
This maintains a buffer of recent data that we can grab for analysis
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/radio/filters/iq.rb', line 50 def collect data i = 0 data_size = data.size while i < data_size remaining = data_size - i space = @bins - @fft_pos actual = [remaining,space].min new_fft_pos = @fft_pos + actual @fft[@fft_pos...new_fft_pos] = data[i...i+actual] @fft_pos = new_fft_pos if @fft_pos == @bins @fft_pos = 0 @next_fft = @fft.dup end i += actual end end |
#detect_energies(spectrum) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/radio/filters/iq.rb', line 112 def detect_energies spectrum result = 0.0 length = @bins.size halfLength = length / 2 start = (0.20 * halfLength).round finish = (0.90 * halfLength).round spectrum = spectrum.abs frag = spectrum[start..finish] min = frag.min max = frag.max threshold = max - (max-min) * 0.5 (start..finish).each do |i| cur = spectrum[length - 1 - i] next unless cur > threshold diff = cur - spectrum[i] next unless diff > 0 result += diff end result end |
#rand_direction ⇒ Object
this is the IQ detection idea from the sdr# project
134 135 136 |
# File 'lib/radio/filters/iq.rb', line 134 def rand_direction rand*2-1 end |
#remove_dc_bias!(data) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/radio/filters/iq.rb', line 94 def remove_dc_bias! data data.collect! do |v| temp = @biasI * (1 - @dc_rate) + v.real * @dc_rate @biasI = temp unless temp.nan? real = v.real - @biasQ temp = @biasQ * (1 - @dc_rate) + v.imag * @dc_rate @biasQ = temp unless temp.nan? imag = v.imag - @biasQ Complex(real,imag) end end |
#setup ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/radio/filters/iq.rb', line 21 def setup @bins = 512 @tries = 5 @dc_rate = 0.00001 @iq_rate = 0.0001 @biasI = 0.0 @biasQ = 0.0 @gain = 1.0 @phase = 0.0 @fft = NArray.scomplex @bins @fft_pos = 0 end |