Class: PWN::SDR::Decoder::POCSAG::BitStream

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

Overview

Incremental framing retains partial codewords and messages across transport chunks and batch sync words. A terminator emits immediately.

Instance Method Summary collapse

Constructor Details

#initialize(baud:) ⇒ BitStream

Returns a new instance of BitStream.



31
32
33
34
35
36
# File 'lib/pwn/sdr/decoder/pocsag.rb', line 31

def initialize(baud:)
  @baud = baud
  @bits = []
  @word_index = nil
  @pending = nil
end

Instance Method Details

#feed(bits, &emit) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/pwn/sdr/decoder/pocsag.rb', line 38

def feed(bits, &emit)
  @bits.concat(bits)
  loop do
    if @word_index.nil? || @word_index == 16
      idx = DSP.find_sync(bits: @bits, pattern: FSC, width: 32, max_err: 2)
      unless idx
        @bits.shift([@bits.length - 31, 0].max)
        break
      end
      @bits.shift(idx + 32)
      @word_index = 0
    end
    break if @bits.length < 32

    cw = DSP.bits_to_int(bits: @bits.shift(32))
    cw = POCSAG.correct_word(word: cw)
    unless cw
      @pending = nil
      @word_index += 1
      next
    end
    if cw == IDLE_CW
      emit_pending(&emit)
    elsif cw.nobits?(0x80000000)
      emit_pending(&emit)
      @pending = { ric: (((cw >> 13) & 0x3FFFF) << 3) | (@word_index / 2),
                   func: (cw >> 11) & 3, msg_words: [] }
    elsif @pending
      @pending[:msg_words] << ((cw >> 11) & 0xFFFFF)
    end
    @word_index += 1
  end
end

#flushObject



72
73
74
75
76
77
# File 'lib/pwn/sdr/decoder/pocsag.rb', line 72

def flush(&)
  @pending = nil unless @bits.empty?
  return unless @pending

  emit_pending(&)
end