Class: PWN::SDR::Decoder::Bluetooth::SymbolStream
- Inherits:
-
Object
- Object
- PWN::SDR::Decoder::Bluetooth::SymbolStream
- Defined in:
- lib/pwn/sdr/decoder/bluetooth.rb
Overview
Continuous Ruby FM/NRZ fallback. Unlike a one-shot liquid gmskdem call, filter history and symbol phase survive transport chunks. Also used for DECT and ZigBee's existing FM/NRZ recovery path.
Instance Method Summary collapse
- #feed(samples) ⇒ Object
- #feed_iq(samples) ⇒ Object
-
#initialize(rate:, baud:) ⇒ SymbolStream
constructor
A new instance of SymbolStream.
Constructor Details
#initialize(rate:, baud:) ⇒ SymbolStream
Returns a new instance of SymbolStream.
33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/pwn/sdr/decoder/bluetooth.rb', line 33 def initialize(rate:, baud:) @spb = rate.to_f / baud raise ArgumentError, 'sample rate must be at least twice the baud' if @spb < 2 @phase = @spb / 2 @previous_iq = nil @previous_input = 0.0 @dc = 0.0 @previous = 0.0 @window = Array.new([(@spb / 4).round, 1].max, 0.0) @slot = 0 @sum = 0.0 end |
Instance Method Details
#feed(samples) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/pwn/sdr/decoder/bluetooth.rb', line 61 def feed(samples) bits = [] samples.each do |x| @dc = x - @previous_input + (0.995 * @dc) @previous_input = x @sum += @dc - @window[@slot] @window[@slot] = @dc @slot = (@slot + 1) % @window.length v = @sum / @window.length @phase = @spb / 2 if (@previous.negative? && v >= 0) || (@previous.positive? && v.negative?) @phase -= 1 if @phase <= 0 bits << (v.negative? ? 0 : 1) @phase += @spb end @previous = v end bits end |
#feed_iq(samples) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/pwn/sdr/decoder/bluetooth.rb', line 47 def feed_iq(samples) audio = [] samples.each_slice(2) do |re, im| next unless im if @previous_iq pr, pi = @previous_iq audio << Math.atan2((im * pr) - (re * pi), (re * pr) + (im * pi)) end @previous_iq = [re, im] end feed(audio) end |