Class: PWN::SDR::Decoder::ADSB::DemodIQ
- Inherits:
-
Object
- Object
- PWN::SDR::Decoder::ADSB::DemodIQ
- Defined in:
- lib/pwn/sdr/decoder/adsb.rb
Overview
Streaming I/Q demod for Base.run_iq.
Instance Method Summary collapse
- #feed_iq(samples, rate: nil, &emit) ⇒ Object
-
#initialize(rate: 2_000_000, reference: nil) ⇒ DemodIQ
constructor
A new instance of DemodIQ.
Constructor Details
#initialize(rate: 2_000_000, reference: nil) ⇒ DemodIQ
Returns a new instance of DemodIQ.
29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/pwn/sdr/decoder/adsb.rb', line 29 def initialize(rate: 2_000_000, reference: nil) raise ArgumentError, 'Mode S requires sample rate 2_000_000' unless (rate.to_f - 2_000_000).zero? @reference = reference @rate = rate.to_f @spb = @rate / 1_000_000.0 # samples per µs (expect ~2) @mag = [] @seen = {} @cpr = {} @sample_offset = 0 end |
Instance Method Details
#feed_iq(samples, rate: nil, &emit) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/pwn/sdr/decoder/adsb.rb', line 41 def feed_iq(samples, rate: nil, &emit) @rate = rate.to_f if rate @spb = @rate / 1_000_000.0 raise ArgumentError, 'Mode S requires sample rate 2_000_000' unless @rate == 2_000_000 samples = [@pending_i] + samples if @pending_i @pending_i = samples.length.odd? ? samples.last : nil samples = samples[0...-1] if @pending_i m2 = PWN::SDR::Decoder::DSP.mag_sq(iq: samples) @mag.concat(m2) # Scan the entire buffer FIRST so frames that land earlier in a # multi-ms chunk are not discarded by the ring-buffer clamp below. # Only AFTER scan() has consumed what it can do we cap residual # history (frame + preamble headroom ≈ 0.5 ms, keep 50 ms). scan(&emit) max = (@rate * 0.05).to_i return unless @mag.length > max @sample_offset += @mag.length - max @mag.shift(@mag.length - max) end |