Class: PWN::SDR::Decoder::GSM::SCHDemodIQ
- Inherits:
-
Object
- Object
- PWN::SDR::Decoder::GSM::SCHDemodIQ
- Defined in:
- lib/pwn/sdr/decoder/gsm.rb
Overview
Noncoherent SCH receiver for channelized GMSK, BT=0.3. Searches sample timing against differentially precoded ETSC and estimates CFO from its two discriminator levels. No multipath equalizer or BCCH/TCH.
Instance Attribute Summary collapse
-
#backend ⇒ Object
readonly
Returns the value of attribute backend.
Instance Method Summary collapse
- #feed_iq(samples, rate: nil) ⇒ Object
-
#initialize(rate:, native: true) ⇒ SCHDemodIQ
constructor
A new instance of SCHDemodIQ.
Constructor Details
#initialize(rate:, native: true) ⇒ SCHDemodIQ
Returns a new instance of SCHDemodIQ.
101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/pwn/sdr/decoder/gsm.rb', line 101 def initialize(rate:, native: true) @rate = Float(rate) raise ArgumentError, 'SCH IQ needs at least four samples per symbol' unless @rate.finite? && @rate >= 1_083_333 @spb = @rate / SYMBOL_RATE @audio = [] @state = {} @cursor = 0 @offset = 0 @training = SCH_ETSC.each_cons(2).map { |a, b| a == b ? 1 : -1 } @backend = :ruby load_native if native end |
Instance Attribute Details
#backend ⇒ Object (readonly)
Returns the value of attribute backend.
99 100 101 |
# File 'lib/pwn/sdr/decoder/gsm.rb', line 99 def backend @backend end |
Instance Method Details
#feed_iq(samples, rate: nil) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/pwn/sdr/decoder/gsm.rb', line 115 def feed_iq(samples, rate: nil) raise ArgumentError, 'SCH sample rate cannot change during a stream' if rate && (rate.to_f - @rate).abs > 0.5 @audio.concat(DSP.fm_demod_iq(iq: samples, state: @state)) span = (148 * @spb).ceil packed = @audio.pack('d*') if @scanner && @audio.length > span while @cursor + span < @audio.length if packed @cursor = @scanner.pwn_gsm_search(packed, @audio.length, @cursor, @spb, @training_packed) break unless @cursor + span < @audio.length end frame = candidate(@cursor) if frame yield frame if block_given? @cursor += span else @cursor += 1 end end @audio.shift(@cursor) @offset += @cursor @cursor = 0 end |