Class: PWN::SDR::Decoder::LTE::DemodIQ

Inherits:
Object
  • Object
show all
Defined in:
lib/pwn/sdr/decoder/lte.rb

Overview

Streaming PSS observation detector for Base.run_iq.

Instance Method Summary collapse

Constructor Details

#initialize(rate:) ⇒ DemodIQ

Returns a new instance of DemodIQ.



144
145
146
147
148
149
# File 'lib/pwn/sdr/decoder/lte.rb', line 144

def initialize(rate:)
  @rate = rate.to_f
  @buf  = []
  @seen = {}
  @pss  = build_pss
end

Instance Method Details

#feed_iq(samples, rate: nil, &emit) ⇒ Object



151
152
153
154
155
156
157
# File 'lib/pwn/sdr/decoder/lte.rb', line 151

def feed_iq(samples, rate: nil, &emit)
  @rate = rate.to_f if rate
  @input ||= []
  @input.concat(samples)
  window = [(@rate * 0.005).round, 1].max * 2
  process_window(@input.shift(window), &emit) while @input.length >= window
end

#process_window(samples) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/pwn/sdr/decoder/lte.rb', line 159

def process_window(samples, &)
  r = PWN::SDR::Decoder::DSP.resample_iq(
    iq: samples, src_rate: @rate, dst_rate: FS_BASE
  )
  @buf.concat(r)
  # need ≥ one 5 ms half-frame @ 1.92 Msps = 9600 complex
  return if @buf.length < 9600 * 2 * 2

  hit = search_pss
  if hit
    # Magnitude-only SSS cannot recover BPSK signs or identify PCI.
    nid1 = nil
    pci  = nid1 ? (3 * nid1) + hit[:nid2] : nil
    key  = pci || "N2=#{hit[:nid2]}"
    unless @seen[key]
      @seen[key] = true
      yield(
        protocol: 'LTE', event: 'cell', modulation: 'OFDMA',
        capability: 'cell-search-only', decoded: false,
        nid2: hit[:nid2], nid1: nid1, pci: pci,
        cfo_hz: hit[:cfo_hz], pss_normalized_correlation: hit[:ratio],
        timing_sample: hit[:pos],
        summary: pci ? "LTE cell PCI=#{pci} (N_ID_1=#{nid1} N_ID_2=#{hit[:nid2]}) CFO=#{hit[:cfo_hz]}Hz" : "LTE PSS lock N_ID_2=#{hit[:nid2]} CFO=#{hit[:cfo_hz]}Hz (SSS unsupported)"
      )
    end
  end
  @buf.shift(@buf.length - (9600 * 2)) if @buf.length > 9600 * 4
end