Module: Denko::OneWire::BusEnumerator

Includes:
Constants
Included in:
Bus
Defined in:
lib/denko/one_wire/bus_enumerator.rb

Constant Summary collapse

PERIPHERAL_CLASSES =

Set FAMILY_CODE in peripheral class, and add the class to this array for the class to be identified during search.

[
  Sensor::DS18B20,
]

Constants included from Constants

Constants::ALARM_SEARCH, Constants::CONVERT_T, Constants::COPY_SCRATCH, Constants::MATCH_ROM, Constants::READ_POWER_SUPPLY, Constants::READ_ROM, Constants::READ_SCRATCH, Constants::RECALL_EEPROM, Constants::SEARCH_ROM, Constants::SKIP_ROM, Constants::WRITE_SCRATCH

Instance Method Summary collapse

Instance Method Details

#_search(branch_mask) ⇒ Object



6
7
8
9
10
# File 'lib/denko/one_wire/bus_enumerator.rb', line 6

def _search(branch_mask)
  reset
  write(SEARCH_ROM)
  board.one_wire_search(pin, branch_mask)
end

#family_lookup(family_code) ⇒ Object



86
87
88
89
90
91
92
93
# File 'lib/denko/one_wire/bus_enumerator.rb', line 86

def family_lookup(family_code)
  PERIPHERAL_CLASSES.each do |klass|
    if (klass.const_defined? "FAMILY_CODE")
      return klass if klass::FAMILY_CODE == family_code
    end
  end
  return nil
end

#found_devicesObject



12
13
14
# File 'lib/denko/one_wire/bus_enumerator.rb', line 12

def found_devices
  @found_devices ||= []
end

#parse_search_result(result) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/denko/one_wire/bus_enumerator.rb', line 44

def parse_search_result(result)
  address, complement = split_search_result(result)

  if (address & complement) > 0
    raise "OneWire device not connected or disconnected during search"
  end

  raise "CRC error during OneWire search" unless Helper.crc(address)

  # Gives 0 at every discrepancy we didn't write 1 for on this search.
  new_discrepancies = address ^ complement

  high_discrepancy = -1
  (0..63).each { |i| high_discrepancy = i if new_discrepancies[i] == 0 }

  # LSByte of address is product family.
  klass = family_lookup(address & 0xFF)

  [{class: klass, address: address}, high_discrepancy]
end

#searchObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/denko/one_wire/bus_enumerator.rb', line 16

def search
  @found_devices = []
  branch_mask = 0
  high_discrepancy = 0

  loop do
    read_using -> { _search(branch_mask) } do |result|
      device, high_discrepancy = parse_search_result(result)
      @found_devices << device
    end

    # No unsearched discrepancies left.
    break if high_discrepancy == -1

    # Force highest new discrepancy to be a 1 on the next search.
    # i.e. Go as deep as possible into each branch found then back out.
    #
    branch_mask = branch_mask | (2 ** high_discrepancy)

    # Clear bits above high_discrepancy so we don't repeat branches.
    # When high_discrepancy < MSB of branch_mask, this moves us
    # one node out, closer to the root, and finishing the search.
    #
    unset_mask = 0xFFFFFFFFFFFFFFFF >> (63 - high_discrepancy)
    branch_mask = branch_mask & unset_mask
  end
end

#split_search_result(data) ⇒ Object

Result is 16 bytes, 8 byte address and complement interleaved LSByte first.



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/denko/one_wire/bus_enumerator.rb', line 66

def split_search_result(data)
  address = 0
  complement = 0

  data.reverse.each_slice(2) do |comp_byte, addr_byte|
    address = (address << 8) | addr_byte
    complement = (complement << 8) | comp_byte
  end

  [address, complement]
end