Class: Denko::SPI::InputRegister
- Inherits:
-
BaseRegister
- Object
- BaseRegister
- Denko::SPI::InputRegister
- Includes:
- Behaviors::Lifecycle
- Defined in:
- lib/denko/spi/input_register.rb
Constant Summary
Constants included from Behaviors::Lifecycle
Behaviors::Lifecycle::CALLBACK_METHODS
Instance Attribute Summary
Attributes inherited from BaseRegister
Attributes included from Peripheral
#spi_bit_order, #spi_frequency, #spi_mode
Attributes included from Behaviors::State
Attributes included from Behaviors::Component
Attributes included from Behaviors::MultiPin
Instance Method Summary collapse
- #any_listening ⇒ 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
- #listening_pins ⇒ Object
- #read ⇒ Object
-
#reading_pins ⇒ Object
Keep track of whether anything is listening or reading a specific pin.
- #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::Lifecycle
Methods inherited from BaseRegister
#is_a_register?, #platform, #state
Methods included from Behaviors::BoardProxy
#analog_read_high, #analog_write_high, #convert_pin, #high, #low, #set_pin_mode, #start_read
Methods included from Behaviors::Subcomponents
#add_component, #add_hw_i2c, #add_hw_spi, #add_single_pin, #components, #hw_i2c_comps, #hw_spi_comps, #remove_component, #remove_hw_i2c, #remove_hw_spi, #remove_single_pin, #single_pin_components
Methods included from Peripheral
#ensure_byte_array, #initialize_pins, #proxy_pin, #spi_listen, #spi_read, #spi_stop, #spi_transfer, #spi_write
Methods included from Behaviors::Callbacks
#add_callback, #callbacks, #pre_callback_filter, #remove_callback
Methods included from Behaviors::State
Methods included from Behaviors::BusPeripheral
Methods included from Behaviors::Component
Methods included from Behaviors::MultiPin
#convert_pins, #proxy_pin, #proxy_states, #require_pin, #require_pins
Instance Method Details
#any_listening ⇒ Object
56 57 58 59 |
# File 'lib/denko/spi/input_register.rb', line 56 def any_listening listening_pins.each { |p| return true if p } 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.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/denko/spi/input_register.rb', line 120 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
46 47 48 49 |
# File 'lib/denko/spi/input_register.rb', line 46 def digital_listen(pin, divider) listen unless any_listening listening_pins[pin] = true end |
#digital_read(pin) ⇒ Object
BoardProxy interface
37 38 39 40 41 42 43 44 |
# File 'lib/denko/spi/input_register.rb', line 37 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).
66 67 68 69 70 71 72 73 74 75 |
# File 'lib/denko/spi/input_register.rb', line 66 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
26 27 28 |
# File 'lib/denko/spi/input_register.rb', line 26 def listen spi_listen(bytes) end |
#listening_pins ⇒ Object
14 15 16 |
# File 'lib/denko/spi/input_register.rb', line 14 def listening_pins @listening_pins ||= Array.new(bytes*8) { false } end |
#read ⇒ Object
22 23 24 |
# File 'lib/denko/spi/input_register.rb', line 22 def read spi_read(bytes) end |
#reading_pins ⇒ Object
Keep track of whether anything is listening or reading a specific pin. This might be separate from whether a component is attached or not.
10 11 12 |
# File 'lib/denko/spi/input_register.rb', line 10 def reading_pins @reading_pins ||= Array.new(bytes*8) { false } end |
#stop ⇒ Object
30 31 32 |
# File 'lib/denko/spi/input_register.rb', line 30 def stop spi_stop end |
#stop_listener(pin) ⇒ Object
51 52 53 54 |
# File 'lib/denko/spi/input_register.rb', line 51 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.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/denko/spi/input_register.rb', line 81 def update() # Since overriding update, make sure this is a byte array first. byte_array = ensure_byte_array() bits = byte_array_to_bit_array(byte_array) @callback_mutex.lock if @callbacks && !@callbacks.empty? # Arduino doesn't de-duplicate state. Do it, but honor :force_update callbacks. 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) end @callback_mutex.unlock self.state = bits end |
#update_component(part, pin, value) ⇒ Object
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/denko/spi/input_register.rb', line 105 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. # Always called inside @callback_mutex, so @callbacks, not callbacks elsif reading_pins[pin] && @callbacks[:force_update] part.update(value) end end |