littlewire 0.9 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,55 @@
1
+ # Connects to an LPD6803 LED Pixel of the type sold by ladyada, bliptronics, and alibaba
2
+ # and sends rgb info to the pixel. While these lights have worse colour reproduction than
3
+ # the PWM in Little Wire, they're chainable so you can run hundreds off one Little Wire!
4
+ #
5
+ # This sort: http://bliptronics.com/item.aspx?ItemID=113
6
+ #
7
+ # Note if you're running more than five or so from a littlewire you should power them
8
+ # with an external power supply instead of Little Wire's VCC pin
9
+ require '../lib/littlewire'
10
+
11
+ wire = LittleWire.connect
12
+ spi = wire.spi
13
+
14
+ wire.pin_mode :pin1 => :output, :pin3 => :output
15
+
16
+ def lpd6803_data red, green, blue
17
+ # TODO: could add some dithering here
18
+ bits = [green, blue, red].map { |v| (v * 31).round.to_s(2).rjust(5, '0') }
19
+ "1#{bits.join ''}".to_i(2)
20
+ end
21
+
22
+ $lights = [[1.0, 0.0, 1.0]] # just one light, with red, green, blue set to bright violet
23
+ def update_lights
24
+ new_sequence = $lights.map { |pix| lpd6803_data(*pix) }
25
+ new_sequence.unshift 0, 0 # add start frame
26
+ $data_sequence = new_sequence
27
+ end
28
+
29
+ update_lights
30
+
31
+ spi.delay = 10
32
+
33
+ $x = 0.0
34
+
35
+ require 'benchmark'
36
+ Benchmark.benchmark do
37
+ for i in 1..1000000
38
+ wire.digital_write pin1: true
39
+ end
40
+ end
41
+ # loop do
42
+ # $data_sequence.each_slice(2) do |cells|
43
+ # spi.send cells.pack('S>*')
44
+ # end
45
+ #
46
+ # $lights = [[0.0, $x % 1.0, 0.0]]
47
+ # $x += 1.0/32.0
48
+ # update_lights
49
+ #
50
+ # # and now we use software pwm to run the light's clock for a little while
51
+ # wire.software_pwm_write(pin2: 127)
52
+ # sleep (1.0/32.0)
53
+ # wire.software_pwm_enabled = false
54
+ # end
55
+
@@ -0,0 +1,20 @@
1
+ require '../lib/littlewire.rb'
2
+ wire = LittleWire.connect
3
+ pin = :pin1
4
+ speed = 1
5
+ num_leds = 64
6
+
7
+ loop do
8
+ puts "red"
9
+ wire.ws2811.colors = ['red'] * num_leds
10
+ wire.ws2811.output pin
11
+ sleep speed
12
+ puts "green"
13
+ wire.ws2811.colors = ['green'] * num_leds
14
+ wire.ws2811.output pin
15
+ sleep speed
16
+ puts "blue"
17
+ wire.ws2811.colors = ['blue'] * num_leds
18
+ wire.ws2811.output pin
19
+ sleep speed
20
+ end
@@ -0,0 +1,25 @@
1
+ require '../lib/littlewire.rb'
2
+ wire = LittleWire.connect
3
+ num_pixels = ARGV.first.to_i
4
+
5
+ lit = 0
6
+ loop do
7
+
8
+ text_output = ['-'] * num_pixels
9
+ text_output[lit] = '*'
10
+ puts text_output.join
11
+
12
+ wire.ws2811.colors = num_pixels.times.map do |idx|
13
+ if idx == lit
14
+ 'white'.to_color
15
+ else
16
+ 'black'.to_color
17
+ end
18
+ end
19
+ wire.ws2811.output :pin1
20
+
21
+ lit += 1
22
+ lit %= num_pixels
23
+
24
+ sleep 0.01
25
+ end
@@ -0,0 +1,39 @@
1
+ # Send up to 64 colours to a string of WS2812 LEDs or 800khz (version 2) Adafruit Flora NeoPixels
2
+ # Any 800khz mode ws2811 pixels will work
3
+ require '../lib/littlewire.rb'
4
+ wire = LittleWire.connect
5
+
6
+ puts DATA.read # print out the little ascii art thing at the end of this file
7
+ puts "Which pin to use for data output?"
8
+ print "Enter pin number: "
9
+ output_pin = gets.gsub(/[^0-9]/, '').to_i
10
+
11
+ print "Enter 1st color: "
12
+ wire.ws2811.colors = [gets.strip.to_color]
13
+ wire.ws2811.output(output_pin) # output our first color
14
+
15
+ titles = ['1st', '2nd', '3rd']
16
+
17
+ 63.times do |idx|
18
+ print "Enter #{titles[idx + 1] || "#{idx + 2}th"} color: "
19
+ gotten = gets.strip
20
+ break if gotten.empty?
21
+ # add colour to array
22
+ wire.ws2811.colors.push gotten.to_color
23
+ wire.ws2811.output(output_pin) # output the colours to the string
24
+ end
25
+
26
+ puts "All done!"
27
+
28
+ __END__
29
+ LittleWire connector: | Digispark Board:
30
+ /-----\ | _________
31
+ pin_1 | o o | vcc | _____| o| ds5
32
+ pin_2 | o o | pin 4 | |----- o| (usb - not available)
33
+ pin_3 | o o | gnd | |----- o| (usb - not available)
34
+ \-----/ | |----- o| ds2
35
+ |----- o| ds1
36
+ |_o_o_o__o| ds0
37
+ 5 g v
38
+ v n c
39
+ d c
@@ -58,7 +58,7 @@ module LittleWire::Digital
58
58
  # `sensor_a, sensor_b = my_wire.digital_read(:pin1, :pin2)` which reads both pins at
59
59
  # the exact same instant in just one USB request, returning an array of the results
60
60
  #
61
- # digital_read tends to work best when the pin in :input mode. See also #pin_mode
61
+ # digital_read works best when the pin is in :input mode. See also #pin_mode
62
62
  def digital_read *args
63
63
  raise "Incorrect Arguments" if args.length < 1
64
64
  pins = args.flatten
@@ -11,6 +11,7 @@ require_relative 'servo'
11
11
  require_relative 'spi'
12
12
  require_relative 'i2c'
13
13
  require_relative 'one-wire'
14
+ require_relative 'ws2811'
14
15
 
15
16
  # LittleWire class represents LittleWire's connected to your computer via USB
16
17
  #
@@ -25,10 +26,10 @@ class LittleWire
25
26
 
26
27
  # pin name to numeric internal code maps
27
28
  DigitalPinMap = { # maps common names to bit positions in PORTB
28
- pin1: 1, d1: 1, miso: 1, pwm_b: 1, pwm_2: 1,
29
- pin2: 2, d2: 2, sck: 2,
30
- pin3: 5, d3: 5, reset: 5,
31
- pin4: 0, d4: 0, mosi: 0, pwm_a: 0, pwm_1: 0 }
29
+ pin1: 1, d1: 1, miso: 1, pwm_b: 1, pwm_2: 1, ds1: 1,
30
+ pin2: 2, d2: 2, sck: 2, ds2: 2,
31
+ pin3: 5, d3: 5, reset: 5, ds5: 5,
32
+ pin4: 0, d4: 0, mosi: 0, pwm_a: 0, pwm_1: 0, ds0: 0 }
32
33
  AnalogPinMap = { # maps common names to switch index in littlewire firmware
33
34
  a1: 0, adc_1: 0, reset: 0, pin3: 0, d3: 0,
34
35
  a2: 1, adc_2: 1, sck: 1, pin2: 1, d2: 1,
@@ -37,9 +38,9 @@ class LittleWire
37
38
  pwm_b: 1, pwm_1: 1, d1: 1, pin1: 1, miso: 1,
38
39
  pwm_a: 0, pwm_2: 0, d4: 0, pin4: 0, mosi: 0 }
39
40
  SoftwarePWMPinMap = { # TODO: figure out which pins these are
40
- softpwm_1: 0, softpwm_a: 0,
41
- softpwm_2: 1, softpwm_b: 1,
42
- softpwm_3: 2, softpwm_c: 2 }
41
+ softpwm_1: 0, softpwm_a: 0, pin4: 0, d4: 0, mosi: 0, pwm_a: 0, pwm_1: 0,
42
+ softpwm_2: 1, softpwm_b: 1, pin1: 1, d1: 1, miso: 1, pwm_b: 1, pwm_2: 1,
43
+ softpwm_3: 2, softpwm_c: 2, pin2: 2, d2: 2, sck: 2 }
43
44
  GenericPinMap = { # generic pinmap used by [] and []= methods to refer to anything
44
45
  d1: [:digital, :pin1],
45
46
  d2: [:digital, :pin2],
@@ -65,7 +66,7 @@ class LittleWire
65
66
  softpwm_c: [:software_pwm, :softpwm_c],
66
67
  }
67
68
 
68
- SupportedVersions = ['1.1', '1.0'] # in order of newness. # TODO: Add version 1.0?
69
+ SupportedVersions = ['1.2', '1.1', '1.0'] # in order of newness. # TODO: Add version 1.0?
69
70
 
70
71
 
71
72
  # An array of all unclaimed littlewires connected to computer via USB
@@ -120,11 +121,11 @@ class LittleWire
120
121
 
121
122
  # implementations of littlewire functions
122
123
  # - generic requests
123
- def echo; control_transfer(function: :echo, dataIn: 8).unpack('S<*'); end # echo's usb request for testing
124
- def read; control_transfer(function: :read, wIndex: 0, dataIn: 1); end
125
- def write byte; control_transfer(function: :write, wIndex: 0, wValue: byte); end
126
- def clear_bit bit; control_transfer(function: :clear_bit, wIndex: 0, wValue: bit); end
127
- def set_bit bit; control_transfer(function: :set_bit, wIndex: 0, wValue: bit); end
124
+ #def echo; control_transfer(function: :echo, dataIn: 8).unpack('S<*'); end # echo's usb request for testing
125
+ #def read; control_transfer(function: :read, wIndex: 0, dataIn: 1); end
126
+ #def write byte; control_transfer(function: :write, wIndex: 0, wValue: byte); end
127
+ #def clear_bit bit; control_transfer(function: :clear_bit, wIndex: 0, wValue: bit); end
128
+ #def set_bit bit; control_transfer(function: :set_bit, wIndex: 0, wValue: bit); end
128
129
  # - programming requests
129
130
  #def power_up sck_period, reset; control_transfer(function: :power_up, wIndex: sck_period, wValue: reset ? 1 : 0); end
130
131
  #def power_down; control_transfer(function: :power_down); end
@@ -151,12 +152,23 @@ class LittleWire
151
152
  @i2c ||= I2C.new(self)
152
153
  end
153
154
 
154
- # get the 1wire interface (requires firmware 1.1 or newer
155
+ # get the 1wire interface (requires firmware 1.1 or newer)
155
156
  def one_wire
156
157
  raise "You need to update your LittleWire firmware to version 1.1 to use One Wire" unless version_hex >= 0x11
157
158
  @one_wire ||= OneWire.new(self)
158
159
  end
159
160
 
161
+ # get the ws2811 led strip interface (requires firmware 1.2 or newer)
162
+ # optionally call with pin number to preset it
163
+ def ws2811 pin = false
164
+ raise "You need to update your LittleWire firmware to version 1.2 to use One Wire" unless version_hex >= 0x12
165
+ @ws2811 ||= Array.new
166
+ @ws2811[pin || 0] ||= WS2811.new(self, pin)
167
+ return @ws2811[pin || 0]
168
+ end
169
+
170
+ alias_method :ws2812, :ws2811
171
+
160
172
 
161
173
 
162
174
  # translate calls with arduino-style lowerCamelCase method names in to ruby-style underscored_method_names
@@ -259,7 +271,9 @@ class LittleWire
259
271
  :onewire_read_bit, # 50
260
272
  :onewire_write_bit, # 51
261
273
  :pic_24f_programming, # 52 - experimental
262
- :pic_24f_sendsix # 53 - experimental
274
+ :pic_24f_sendsix, # 53 - experimental
275
+ :ws2812_write, # 54 - experimental
276
+ :ws2812_preload # 55 - experimental
263
277
  # special cases
264
278
  # pic 24f send bytes - request = 0xD*
265
279
  # i2c send multiple messages - request = 0xE* ### experimental ###
@@ -278,10 +292,9 @@ class LittleWire
278
292
 
279
293
  # calculate usb request type
280
294
  def usb_request_type opts #:nodoc:
281
- c = LIBUSB::Call
282
- value = c::RequestTypes[:REQUEST_TYPE_VENDOR] | c::RequestRecipients[:RECIPIENT_DEVICE]
283
- value |= c::EndpointDirections[:ENDPOINT_OUT] if opts.has_key? :dataOut
284
- value |= c::EndpointDirections[:ENDPOINT_IN] if opts.has_key? :dataIn
295
+ value = LIBUSB::REQUEST_TYPE_VENDOR | LIBUSB::RECIPIENT_DEVICE
296
+ value |= LIBUSB::ENDPOINT_OUT if opts.has_key? :dataOut
297
+ value |= LIBUSB::ENDPOINT_IN if opts.has_key? :dataIn
285
298
  return value
286
299
  end
287
300
 
@@ -34,10 +34,17 @@ module LittleWire::SoftwarePWM
34
34
  end
35
35
 
36
36
  # Set the value of a single software pwm channel - value must be a number between 0 and 255 inclusive
37
- def software_pwm_write channel, value
38
- state = self.software_pwm
39
- state[get_pin(LittleWire::SoftwarePWMPinMap, channel)] = value
40
- self.software_pwm = state
37
+ def software_pwm_write *args
38
+ if args.first.is_a? Hash
39
+ state = self.software_pwm
40
+ args.first.each do |channel, value|
41
+ state[get_pin(LittleWire::SoftwarePWMPinMap, channel)] = value
42
+ end
43
+ self.software_pwm = state
44
+ else
45
+ raise "Invalid Arguments" unless args.length == 2
46
+ self.software_pwm_write(args.first => args.last)
47
+ end
41
48
  end
42
49
 
43
50
  def is_software_pwm_available?
data/lib/spi.rb CHANGED
@@ -6,12 +6,14 @@ class LittleWire::SPI
6
6
  end
7
7
 
8
8
  # send and receive a message of up to four bytes
9
- def send send, receive, auto_chipselect = false
9
+ def send send, auto_chipselect = false
10
10
  mode = auto_chipselect ? 1 : 0
11
+ bytes = send.bytes.to_a
11
12
  @wire.control_transfer(
12
- wRequest: 0xF0 + send.length + (mode << 3),
13
- wValue: send.bytes[1] << 8 | send.bytes[0],
14
- wIndex: send.bytes[3] << 8 | send.bytes[0]
13
+ bRequest: 0xF0 + send.length + (mode << 3),
14
+ wValue: bytes[1].to_i << 8 | bytes[0].to_i,
15
+ wIndex: bytes[3].to_i << 8 | bytes[2].to_i,
16
+ dataIn: bytes.length
15
17
  )
16
18
  end
17
19
 
@@ -0,0 +1,52 @@
1
+ require 'colorist'
2
+
3
+ # Output colours to ws2812 strips and other 800khz ws2811 led devices
4
+ # To use, simply set colours in the 'colors' array property as css color strings
5
+ # or Colorist::Color objects, then call #output(pin) to send it on it's way
6
+ #
7
+ # Note that this requires firmware v1.2 which is not yet released and there is a
8
+ # maximum of 64 lights in the firmware at the time of writing
9
+ #
10
+ # Also note that you can connect 64 leds to each of the digital pins on the LittleWire
11
+ # or Digispark device, and this enables you a total of 64 * 4 = 256 lights! Neato!
12
+ class LittleWire::WS2811
13
+ attr_accessor :colors
14
+ attr_accessor :pin
15
+
16
+
17
+ def initialize wire, default_pin = false # :nodoc:
18
+ @wire = wire
19
+ @pin = default_pin
20
+ @colors = []
21
+ end
22
+
23
+ # send colours to strip, optionally specifying a pin if not specified via
24
+ # littlewire.ws2811(pin).output
25
+ def output pin = nil
26
+ colors_buffer = @colors.map { |i| i.is_a?(Colorist::Color) ? i : i.to_color }
27
+ output_pin = @wire.get_pin(LittleWire::DigitalPinMap, pin || @pin)
28
+ raise "Must specify output pin for ws2811 strip" unless output_pin.is_a? Integer
29
+
30
+ until colors_buffer.empty?
31
+
32
+ if colors_buffer.length > 1
33
+ color = colors_buffer.shift
34
+
35
+ @wire.control_transfer(
36
+ function: :ws2812_preload,
37
+ wIndex: color.b << 8 | color.r,
38
+ wValue: color.g << 8
39
+ )
40
+ elsif colors_buffer.length == 1
41
+ color = colors_buffer.shift
42
+
43
+ @wire.control_transfer(
44
+ function: :ws2812_write,
45
+ wIndex: color.b << 8 | color.r,
46
+ wValue: color.g << 8 | output_pin
47
+ )
48
+ end
49
+ end
50
+ end
51
+ end
52
+
data/readme.md CHANGED
@@ -53,8 +53,8 @@ lights... whatever floats your boat really. The possabilities are not especially
53
53
  limited. Most projects you might use an Arduino for can be done with a Little Wire
54
54
  if you don't mind leaving a computer turned on connected to it, and with the advent
55
55
  of Raspberry Pi, that's not all that bad of an idea. I use my Little Wire to quickly
56
- test ideas before changing them to C and uploading them to cheaper attiny chips (also
57
- using the Little Wire to program them)
56
+ test ideas before changing them to C and uploading them to cheaper avr tiny chips
57
+ (also using the Little Wire to program them)
58
58
 
59
59
 
60
60
  ### a warning ###
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: littlewire
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.9'
4
+ version: 0.9.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-20 00:00:00.000000000 Z
12
+ date: 2013-05-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: libusb
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: 0.2.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: colorist
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.0.2
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.0.2
30
46
  description: A little library for a little wire. Providing a pure ruby interface (via
31
47
  the nonpure libusb gem) to littlewire.cc's wonderful gadget. littlewire.rb provides
32
48
  general purpose digital IO, pulse width modulation analog outputs, analog inputs,
@@ -46,10 +62,15 @@ files:
46
62
  - lib/servo.rb
47
63
  - lib/software-pwm.rb
48
64
  - lib/spi.rb
65
+ - lib/ws2811.rb
49
66
  - readme.md
50
67
  - license.txt
51
68
  - examples/blinky.rb
52
69
  - examples/fadey.rb
70
+ - examples/led pixel.rb
71
+ - examples/ws2811 colors.rb
72
+ - examples/ws2811 scan.rb
73
+ - examples/ws2811.rb
53
74
  homepage: http://creativepony.com/littlewire/
54
75
  licenses: []
55
76
  post_install_message:
@@ -72,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
93
  version: '0'
73
94
  requirements: []
74
95
  rubyforge_project:
75
- rubygems_version: 1.8.21
96
+ rubygems_version: 1.8.23
76
97
  signing_key:
77
98
  specification_version: 3
78
99
  summary: A tiny library for littlewire.cc usb devices