Class: LittleWire
- Inherits:
-
Object
- Object
- LittleWire
- Includes:
- Analog, Digital, HardwarePWM, Servo, SoftwarePWM
- Defined in:
- lib/littlewire.rb,
lib/littlewire.rb,
lib/littlewire/version.rb,
lib/littlewire/gadgets/nunchuck.rb
Overview
A little library for a little wire, by Bluebie Provides an arduino or wiring style interface to the LittleWire device’s IO features and provides a nicer invented ruby-style interface also.
LittleWire class represents LittleWire’s connected to your computer via USB
Most of the time you’ll only have one LittleWire - in this case, use LittleWire.connect to get ahold of your wire. If you have more than one, you can use LittleWire.all to fetch an array of them
Defined Under Namespace
Modules: Analog, Digital, HardwarePWM, OneWire, Servo, SoftwarePWM Classes: I2C, Nunchuck, SPI, WS2811
Constant Summary collapse
- DigitalPinMap =
pin name to numeric internal code maps
{ # maps common names to bit positions in PORTB pin1: 1, d1: 1, miso: 1, pwm_b: 1, pwm_2: 1, ds1: 1, pin2: 2, d2: 2, sck: 2, ds2: 2, pin3: 5, d3: 5, reset: 5, ds5: 5, pin4: 0, d4: 0, mosi: 0, pwm_a: 0, pwm_1: 0, ds0: 0 }
- AnalogPinMap =
maps common names to switch index in littlewire firmware
{ # maps common names to switch index in littlewire firmware a1: 0, adc_1: 0, reset: 0, pin3: 0, d3: 0, ds5: 0, a2: 1, adc_2: 1, sck: 1, pin2: 1, d2: 1, ds2: 1, temperature: 2, temp: 2 }
- HardwarePWMPinMap =
maps common pin names to @hardware_pwm array index
{ # maps common pin names to @hardware_pwm array index pwm_b: 1, pwm_1: 1, d1: 1, pin1: 1, miso: 1, pwm_a: 0, pwm_2: 0, d4: 0, pin4: 0, mosi: 0 }
- SoftwarePWMPinMap =
TODO: figure out which pins these are
{ # TODO: figure out which pins these are softpwm_1: 0, softpwm_a: 0, pin4: 0, d4: 0, mosi: 0, pwm_a: 0, pwm_1: 0, softpwm_2: 1, softpwm_b: 1, pin1: 1, d1: 1, miso: 1, pwm_b: 1, pwm_2: 1, softpwm_3: 2, softpwm_c: 2, pin2: 2, d2: 2, sck: 2 }
- GenericPinMap =
generic pinmap used by [] and []= methods to refer to anything
{ # generic pinmap used by [] and []= methods to refer to anything d1: [:digital, :pin1], d2: [:digital, :pin2], d3: [:digital, :pin3], d4: [:digital, :pin4], pin1: [:digital, :pin1], pin2: [:digital, :pin2], pin3: [:digital, :pin3], pin4: [:digital, :pin4], a1: [:analog, :a1], a2: [:analog, :a2], adc_1: [:analog, :adc_1], adc_1: [:analog, :adc_2], pwm_1: [:hardware_pwm, :pwm_1], pwm_2: [:hardware_pwm, :pwm_2], pwm_a: [:hardware_pwm, :pwm_a], pwm_b: [:hardware_pwm, :pwm_b], softpwm_1: [:software_pwm, :softpwm_1], softpwm_2: [:software_pwm, :softpwm_2], softpwm_3: [:software_pwm, :softpwm_3], softpwm_a: [:software_pwm, :softpwm_a], softpwm_b: [:software_pwm, :softpwm_b], softpwm_c: [:software_pwm, :softpwm_c], }
- SupportedVersions =
in order of newness.
['1.3','1.2', '1.1', '1.0']
- Functions =
functions offered by the LittleWire
[ ## Generic requests :echo, # echo test 0 :read, # read byte (wIndex:address) 1 :write, # write byte (wIndex:address, wValue:value) 2 :clear_bit, # clear bit (wIndex:address, wValue:bitno) 3 :set_bit, # set bit (wIndex:address, wValue:bitno) 4 ## Programming requests :power_up, # apply power (wValue:SCK-period, wIndex:RESET) 5 :power_down, # remove power from chip 6 :spi, # issue SPI command (wValue:c1c0, wIndex:c3c2) 7 :poll_bytes, # set poll bytes for write (wValue:p1p2) 8 :flash_read, # read flash (wIndex:address) 9 :flash_write, # write flash (wIndex:address, wValue:timeout) 10 :eeprom_read, # read eeprom (wIndex:address) 11 :eeprom_write, # write eeprom (wIndex:address, wValue:timeout) 12 ## Additional requests - ihsanKehribar :pin_set_input, # 13 :pin_set_output, # 14 :read_adc, # 15 :start_pwm, # 16 :update_pwm_compare, # 17 :pin_set_high, # 18 :pin_set_low, # 19 :pin_read, # 20 :single_spi, # 21 :change_pwm_prescale, # 22 :setup_spi, # 23 :setup_i2c, # 24 :i2c_begin_tx, # 25 :i2c_add_buffer, # 26 :i2c_send_buffer, # 27 :spi_add_buffer, # 28 :spi_send_buffer, # 29 :i2c_request_from, # 30 :spi_update_delay, # 31 :stop_pwm, # 32 :debug_spi, # 33 :version, # 34 :analog_init, # 35 :reserved, :reserved, :reserved, :reserved, :read_buffer, # 40 :onewire_reset_pulse, # 41 :onewire_send_byte, # 42 :onewire_read_byte, # 43 :i2c_init, # 44 :i2c_begin, # 45 :i2c_read, # 46 :init_softpwm, # 47 :update_softpwm, # 48 :i2c_update_delay, # 49 :onewire_read_bit, # 50 :onewire_write_bit, # 51 :pic_24f_programming, # 52 - experimental :pic_24f_sendsix, # 53 - experimental :ws2812, # 54 - experimental # special cases # pic 24f send bytes - request = 0xD* # i2c send multiple messages - request = 0xE* ### experimental ### # spi multiple message send - request = 0xF* ]
- Version =
'0.9.11'
Constants included from HardwarePWM
HardwarePWM::PWMPrescaleSettings
Constants included from Analog
Constants included from Digital
Digital::BulkWriteBitmask, Digital::BulkWriteDefaultStates, Digital::EnableBulkWrite
Instance Attribute Summary
Attributes included from SoftwarePWM
Attributes included from HardwarePWM
Class Method Summary collapse
-
.all ⇒ Object
An array of all unclaimed littlewires connected to computer via USB.
-
.connect ⇒ Object
Frst littlewire connected to this computer via USB - good when you only have one.
-
.create_destructor(io) ⇒ Object
creates a lambda to close usb device when LittleWire is deallocated, without LittleWire instance closured in to it recursively.
-
.version ⇒ Object
correct interface, to enable dynamic stuff later if need be:.
Instance Method Summary collapse
-
#[](name) ⇒ Object
get the value of something.
-
#[]=(name, value) ⇒ Object
set the value of something.
-
#control_transfer(opts = {}) ⇒ Object
transfer data between usb device and this program.
-
#finished ⇒ Object
Call finished when you’re done with the LittleWire to release it for other programs to use.
-
#get_boolean(value) ⇒ Object
translate possible literal values in to a boolean true or false (meaning high or low).
-
#get_pin(map, value) ⇒ Object
lookup a pin name in a map and return it’s raw identifier.
-
#i2c ⇒ Object
get the I2C interface.
-
#initialize(devref) ⇒ LittleWire
constructor
initializes a LittleWire with a libusb device reference and some default values - does not talk to device.
-
#io ⇒ Object
raw opened device.
-
#method_missing(name, *args, &proc) ⇒ Object
translate calls with arduino-style lowerCamelCase method names in to ruby-style underscored_method_names.
-
#nunchuck ⇒ Object
get Wii Nunchuck interface.
-
#one_wire ⇒ Object
get the 1wire interface (requires firmware 1.1 or newer).
-
#spi ⇒ Object
get the SPI interface.
-
#usb_request_type(opts) ⇒ Object
calculate usb request type.
-
#version ⇒ Object
Returns version number of firmware on LittleWire hardware.
-
#version_hex ⇒ Object
returns version code number (treat it as a hex number).
-
#ws2811(pin = false) ⇒ Object
(also: #ws2812)
get the ws2811 led strip interface (requires firmware 1.2 or newer) optionally call with pin number to preset it.
Methods included from Servo
Methods included from SoftwarePWM
#is_software_pwm_available?, #software_pwm, #software_pwm=, #software_pwm_read, #software_pwm_write
Methods included from HardwarePWM
#hardware_pwm, #hardware_pwm=, #hardware_pwm_prescale=, #hardware_pwm_read, #hardware_pwm_write
Methods included from Analog
Methods included from Digital
#digital_read, #digital_write, #pin_mode
Constructor Details
#initialize(devref) ⇒ LittleWire
initializes a LittleWire with a libusb device reference and some default values - does not talk to device
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/littlewire.rb', line 89 def initialize devref #:nodoc: @device = devref @hardware_pwm_enabled = :unknown @hardware_pwm_prescale = :unknown @hardware_pwm = [0, 0] @software_pwm_enabled = :unknown @software_pwm = [0, 0, 0] # shut everything down, trying to setup littlewire in consistent initial state in case previous programs # messed with it's state self.software_pwm_enabled = false if version_hex >= 0x11 self.hardware_pwm_enabled = false self.pin_mode(pin1: :input, pin2: :input, pin3: :input, pin4: :input) self.digital_write(pin1: :gnd, pin2: :gnd, pin3: :gnd, pin4: :gnd) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &proc) ⇒ Object
translate calls with arduino-style lowerCamelCase method names in to ruby-style underscored_method_names
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/littlewire.rb', line 179 def method_missing name, *args, &proc underscorized = name.to_s.gsub(/([a-z])([A-Z])/) { "#{$1}_#{$2}" }.downcase # make underscored equivilent return send(underscorized, *args, &proc) if respond_to? underscorized # translate casing style if we can find an equivilent read_only = name.to_s.gsub('=', '').to_sym if GenericPinMap.has_key? read_only if name.to_s.end_with? '=' return (self[read_only] = args.first) else return self[read_only] end end super # default behaviour end |
Class Method Details
.all ⇒ Object
An array of all unclaimed littlewires connected to computer via USB
75 76 77 78 79 80 81 82 |
# File 'lib/littlewire.rb', line 75 def self.all usb = LIBUSB::Context.new usb.devices.select { |device| device.idProduct == 0x0c9f && device.idVendor == 0x1781 && device.product == 'USBtinySPI' }.map { |device| self.new(device) } end |
.connect ⇒ Object
Frst littlewire connected to this computer via USB - good when you only have one
85 |
# File 'lib/littlewire.rb', line 85 def self.connect; all.first; end |
.create_destructor(io) ⇒ Object
creates a lambda to close usb device when LittleWire is deallocated, without LittleWire instance closured in to it recursively
107 108 109 110 111 |
# File 'lib/littlewire.rb', line 107 def self.create_destructor io #:nodoc: lambda do io.close end end |
.version ⇒ Object
correct interface, to enable dynamic stuff later if need be:
5 6 7 |
# File 'lib/littlewire/version.rb', line 5 def self.version LittleWire::Version end |
Instance Method Details
#[](name) ⇒ Object
get the value of something
197 198 199 200 201 |
# File 'lib/littlewire.rb', line 197 def [] name pin = GenericPinMap[name.to_sym] raise "Unknown Pin '#{name}'" unless pin self.send "#{pin[0]}_read", pin[1] end |
#[]=(name, value) ⇒ Object
set the value of something
204 205 206 207 208 |
# File 'lib/littlewire.rb', line 204 def []= name, value pin = GenericPinMap[name.to_sym] raise "Unknown Pin '#{name}'" unless pin self.send "#{pin[0]}_write", pin[1], value end |
#control_transfer(opts = {}) ⇒ Object
transfer data between usb device and this program
300 301 302 303 304 305 306 307 308 |
# File 'lib/littlewire.rb', line 300 def control_transfer(opts = {}) #:nodoc: opts[:bRequest] = Functions.index(opts.delete(:function)) if opts[:function] io.control_transfer({ wIndex: 0, wValue: 0, bmRequestType: usb_request_type(opts), timeout: 5000 }.merge opts) end |
#finished ⇒ Object
Call finished when you’re done with the LittleWire to release it for other programs to use. You can always claim it again later by using any of the methods on this class which communicate over USB
115 116 117 118 119 120 121 |
# File 'lib/littlewire.rb', line 115 def finished if @io ObjectSpace.undefine_finalizer(self) # remove usb closer finalizer @io.close @io = nil end end |
#get_boolean(value) ⇒ Object
translate possible literal values in to a boolean true or false (meaning high or low)
219 220 221 222 223 |
# File 'lib/littlewire.rb', line 219 def get_boolean value #:nodoc: # some exceptions value = false if value == :low or value == 0 or value == nil or value == :off or value == :ground or value == :gnd !! value # double invert value in to boolean form end |
#get_pin(map, value) ⇒ Object
lookup a pin name in a map and return it’s raw identifier
212 213 214 215 216 |
# File 'lib/littlewire.rb', line 212 def get_pin map, value #:nodoc: value = value.to_sym if value.is_a? String value = map[value] if map.has_key? value value end |
#i2c ⇒ Object
get the I2C interface
153 154 155 |
# File 'lib/littlewire.rb', line 153 def i2c @i2c ||= I2C.new(self) end |
#io ⇒ Object
raw opened device
226 227 228 229 230 231 232 233 234 235 |
# File 'lib/littlewire.rb', line 226 def io #:nodoc: unless @io @io = @device.open ObjectSpace.define_finalizer(self, self.class.create_destructor(@io)) # check for compatible firmware on littlewire device and warn if is unknown warn "Unknown littlewire.cc firmware version #{version} might cause problems" unless SupportedVersions.include? version end @io end |
#nunchuck ⇒ Object
get Wii Nunchuck interface
3 4 5 |
# File 'lib/littlewire/gadgets/nunchuck.rb', line 3 def nunchuck @nunchuck ||= LittleWire::Nunchuck.new self end |
#one_wire ⇒ Object
get the 1wire interface (requires firmware 1.1 or newer)
158 159 160 161 |
# File 'lib/littlewire.rb', line 158 def one_wire raise "You need to update your LittleWire firmware to version 1.1 to use One Wire" unless version_hex >= 0x11 @one_wire ||= OneWire.new(self) end |
#spi ⇒ Object
get the SPI interface
148 149 150 |
# File 'lib/littlewire.rb', line 148 def spi @spi ||= SPI.new(self) end |
#usb_request_type(opts) ⇒ Object
calculate usb request type
311 312 313 314 315 316 |
# File 'lib/littlewire.rb', line 311 def usb_request_type opts #:nodoc: value = LIBUSB::REQUEST_TYPE_VENDOR | LIBUSB::RECIPIENT_DEVICE value |= LIBUSB::ENDPOINT_OUT if opts.has_key? :dataOut value |= LIBUSB::ENDPOINT_IN if opts.has_key? :dataIn return value end |
#version ⇒ Object
Returns version number of firmware on LittleWire hardware
143 144 145 |
# File 'lib/littlewire.rb', line 143 def version @version ||= version_hex.to_s(16).chars.entries.join('.') end |
#version_hex ⇒ Object
returns version code number (treat it as a hex number)
138 139 140 |
# File 'lib/littlewire.rb', line 138 def version_hex @version_hex ||= control_transfer(function: :version, dataIn: 1).unpack('c').first end |
#ws2811(pin = false) ⇒ Object Also known as: ws2812
get the ws2811 led strip interface (requires firmware 1.2 or newer) optionally call with pin number to preset it
165 166 167 168 169 170 171 172 |
# File 'lib/littlewire.rb', line 165 def ws2811 pin = false raise "You need to update your LittleWire firmware to version 1.2 to use One Wire" unless version_hex >= 0x12 @ws2811 ||= Array.new pin = get_pin(LittleWire::DigitalPinMap, pin || 0) raise "Unknown pin #{pin.inspect}" unless pin.is_a? Integer @ws2811[pin] ||= WS2811.new(self, pin) return @ws2811[pin] end |