Class: Denko::SPI::InputRegister
- Inherits:
-
BaseRegister
- Object
- BaseRegister
- Denko::SPI::InputRegister
- Defined in:
- lib/denko/spi/input_register.rb
Instance Attribute Summary
Attributes inherited from BaseRegister
Attributes included from Peripheral
#spi_bit_order, #spi_frequency, #spi_mode
Attributes included from Behaviors::BusPeripheral
Attributes included from Behaviors::Component
Attributes included from Behaviors::Callbacks
Attributes included from Behaviors::SinglePin
Instance Method Summary collapse
- #after_initialize(options = {}) ⇒ Object
- #any_listening ⇒ Object
- #before_initialize(options = {}) ⇒ Object
-
#byte_array_to_bit_array(byte_array) ⇒ Object
Convert array of bytes coming from the register into an array of bits to update self state and give to component callbacks.
- #digital_listen(pin, divider) ⇒ Object
-
#digital_read(pin) ⇒ Object
BoardProxy interface.
-
#enable_proxy ⇒ Object
Mimic Board#update, but in a callback fired through #update.
- #listen ⇒ Object
- #read ⇒ Object
- #stop ⇒ Object
- #stop_listener(pin) ⇒ Object
-
#update(message) ⇒ Object
Override Callbacks#update to make sure we handle :force_update within the main mutex lock.
- #update_component(part, pin, value) ⇒ Object
Methods included from Behaviors::BoardProxy
#convert_pin, #high, #low, #set_pin_mode, #start_read
Methods included from Behaviors::Subcomponents
#add_component, #components, #remove_component, #single_pin_components
Methods included from Peripheral
#spi_listen, #spi_read, #spi_stop, #spi_transfer, #spi_write
Methods included from Behaviors::BusPeripheral
Methods included from Behaviors::Component
Methods included from Behaviors::State
Methods included from Behaviors::Callbacks
#add_callback, #callbacks, #initialize, #pre_callback_filter, #remove_callback
Instance Method Details
#after_initialize(options = {}) ⇒ Object
15 16 17 18 |
# File 'lib/denko/spi/input_register.rb', line 15 def after_initialize(={}) super() enable_proxy end |
#any_listening ⇒ Object
54 55 56 57 |
# File 'lib/denko/spi/input_register.rb', line 54 def any_listening @listening_pins.each { |p| return true if p } false end |
#before_initialize(options = {}) ⇒ Object
5 6 7 8 9 10 11 12 13 |
# File 'lib/denko/spi/input_register.rb', line 5 def before_initialize(={}) super() # # Keep track of whether anything is listening or reading a specific pin. # This might be separate from whether a component is attached or not. # @reading_pins = Array.new(@bytes*8) { false } @listening_pins = Array.new(@bytes*8) { false } end |
#byte_array_to_bit_array(byte_array) ⇒ Object
Convert array of bytes coming from the register into an array of bits to update self state and give to component callbacks.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/denko/spi/input_register.rb', line 114 def byte_array_to_bit_array(byte_array) # # For each array element (1 byte): # decimal number as string -> integer -> padded string of binary digits # -> reverse digits from reading order to array indexing order # -> join digits of all bytes into one string # binary_string = byte_array.map do |byte| byte.to_i.to_s(2).rjust(8, "0").reverse end.join # Split the digits out of the string into individual integers. binary_string.split("").map { |bit| bit.to_i } end |
#digital_listen(pin, divider) ⇒ Object
44 45 46 47 |
# File 'lib/denko/spi/input_register.rb', line 44 def digital_listen(pin, divider) listen unless any_listening @listening_pins[pin] = true end |
#digital_read(pin) ⇒ Object
BoardProxy interface
35 36 37 38 39 40 41 42 |
# File 'lib/denko/spi/input_register.rb', line 35 def digital_read(pin) # Remember what pin was read and force callbacks to run next update. add_callback(:force_update) { Proc.new{} } @reading_pins[pin] = true # Don't actually call #read if already listening. read unless any_listening end |
#enable_proxy ⇒ Object
Mimic Board#update, but in a callback fired through #update. This doesn’t interfere with using the register directly, and doesn’t fire if the board isn’t acting as a proxy (no components).
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/denko/spi/input_register.rb', line 64 def enable_proxy self.add_callback(:board_proxy) do |bit_array| bit_array.each_with_index do |value, pin| components.each do |part| update_component(part, pin, value) if pin == part.pin end @reading_pins[pin] = false end end end |
#listen ⇒ Object
24 25 26 |
# File 'lib/denko/spi/input_register.rb', line 24 def listen spi_listen(@bytes) end |
#read ⇒ Object
20 21 22 |
# File 'lib/denko/spi/input_register.rb', line 20 def read spi_read(@bytes) end |
#stop ⇒ Object
28 29 30 |
# File 'lib/denko/spi/input_register.rb', line 28 def stop spi_stop end |
#stop_listener(pin) ⇒ Object
49 50 51 52 |
# File 'lib/denko/spi/input_register.rb', line 49 def stop_listener(pin) @listening_pins[pin] = false stop unless any_listening end |
#update(message) ⇒ Object
Override Callbacks#update to make sure we handle :force_update within the main mutex lock.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/denko/spi/input_register.rb', line 79 def update() bits = byte_array_to_bit_array(.split(",")) @callback_mutex.synchronize { # # The Arduino code does not de-duplicate repeated state. # Do it here, but if a :force_update callback exists, run anyway. # if (bits != @state)|| @callbacks[:force_update] @callbacks.each_value do |array| array.each { |callback| callback.call(bits) } end end # Remove both :read and :force update while inside the lock. @callbacks.delete(:read) @callbacks.delete(:force_update) } @state = bits end |
#update_component(part, pin, value) ⇒ Object
100 101 102 103 104 105 106 107 108 |
# File 'lib/denko/spi/input_register.rb', line 100 def update_component(part, pin, value) # Update if component is listening and value has changed. if @listening_pins[pin] && (value != @state[pin]) part.update(value) # Also update if the component forced a read. elsif @reading_pins[pin] && @callbacks[:force_update] part.update(value) end end |