Class: PWN::SDR::Decoder::Iridium::RingAlertSymbolsIQ

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

Overview

Input is already channelized, carrier/timing synchronized, one complex sample per symbol at 25 ksym/s. This is NOT a wideband IQ receiver.

Constant Summary collapse

GRAY =
%w[00 01 11 10].freeze

Instance Method Summary collapse

Constructor Details

#initializeRingAlertSymbolsIQ

Returns a new instance of RingAlertSymbolsIQ.



184
185
186
187
# File 'lib/pwn/sdr/decoder/iridium.rb', line 184

def initialize
  @previous = 0
  @bits = +''
end

Instance Method Details

#feed_iq(samples, rate: nil) ⇒ Object

Raises:

  • (ArgumentError)


189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/pwn/sdr/decoder/iridium.rb', line 189

def feed_iq(samples, rate: nil)
  raise ArgumentError, 'IRA symbol IQ requires 25000 samples/s' if rate && rate.to_i != 25_000

  samples.each_slice(2) do |i, q|
    quadrant = ((Math.atan2(q, i) / (Math::PI / 2)) - 0.5).round % 4
    @bits << GRAY[(quadrant - @previous) % 4]
    @previous = quadrant
    start = @bits.index(RingAlert::ACCESS)
    unless start
      @bits = @bits[-24, 24] if @bits.length > 24
      next
    end
    @bits = @bits[start..]
    next if @bits.length < 184 || ((@bits.length - 120) % 64).positive?

    begin
      frame = RingAlert.new.decode(@bits)
    rescue ArgumentError => e
      @bits = @bits[2..] unless e.message == 'Truncated IRA paging section' && @bits.length < 888
      next
    end
    @bits.clear
    yield frame.merge(source: 'symbol-iq', capability: 'IRA-synchronized-symbols', sample_rate: 25_000)
  end
end

#flushObject



215
216
217
# File 'lib/pwn/sdr/decoder/iridium.rb', line 215

def flush
  @bits.clear
end