digiusb 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/digiterm +5 -2
  2. data/lib/digiusb.rb +74 -13
  3. metadata +1 -1
data/bin/digiterm CHANGED
@@ -11,7 +11,6 @@ spark = DigiUSB.sparks.last
11
11
 
12
12
  puts "Attached to #{spark.inspect.green}".blue
13
13
  puts "Type control + c to exit".blue
14
-
15
14
  begin
16
15
  loop do
17
16
  char = spark.getc
@@ -29,7 +28,11 @@ begin
29
28
  end
30
29
  rescue LIBUSB::ERROR_PIPE, LIBUSB::ERROR_NO_DEVICE
31
30
  puts "" # newline
32
- puts "Digispark disconnected or crashed".white_on_red
31
+ puts "Digispark disconnected".white_on_red
32
+ rescue DigiUSB::ErrorCrashed
33
+ puts "" # newline
34
+ puts "Digispark has crashed".white_on_red
35
+ puts " >> Probably need to call DigiUSB.refresh() more frequently in Digispark Program".blue
33
36
  rescue Interrupt
34
37
  puts ""
35
38
  end
data/lib/digiusb.rb CHANGED
@@ -1,28 +1,54 @@
1
+ # The DigiUSB class helps find, connect to, and talk with Digisparks using the DigiUSB arduino library bundled with the Digispark Arduino software.
2
+ # This class aims to work like an IO object, letting you read and write characters, bytes, and strings as if it were a file, socket, or serial port.
3
+ # To get started, grab a list of Digisparks with the DigiUSB.sparks method. Each spark has an inspect method with a unique identifier including the
4
+ # USB device name (usually DigiUSB), and some numbers representing which ports and hubs each spark connects to. To begin with, DigiUSB.sparks.last
5
+ # works well if you only intend to have one digispark connected to your computer. Eventually the device name (aka "product name") will hopefully
6
+ # provide a simple way to differentiate different digisparks.
7
+ #
8
+ # Once you have a reference to a Digispark, you can start using it as if it were an IO object immediately with methods like getc and putc.
9
+ # As soon as you start interacting with the Digispark using these reading and writing methods the Digispark will be claimed to your ruby program
10
+ # and will be unavailable to other programs until you do one of: close the ruby program, or unplug and plug back in the Digispark.
11
+ #
12
+ # Note also that calling DigiUSB.sparks can sometimes disrupt program uploads, so if you're polling waiting for a digispark to appear you may see
13
+ # some programming errors in the Digispark Arduino software.
14
+
1
15
  require 'libusb'
2
16
 
3
17
  # simple IO-like read/write access to a digispark using the DigiUSB library
4
18
  class DigiUSB
5
- ProductID = 0x05df
6
- VendorID = 0x16c0
7
- Manufacturer = "digistump.com"
19
+ ProductID = 0x05df # product id number from Digistump
20
+ VendorID = 0x16c0 # vendor id number for Digistump
21
+ Manufacturer = "digistump.com" # manufacturer string is static
8
22
  Timeout = 1_000 # one second till device crashes due to lack of calling DigiUSB.refresh()
23
+ DefaultPollingFrequency = 15 # 15hz when waiting for data to be printed
9
24
 
25
+ # :nodoc: initialize a new DigiUSB object using a libusb device object
10
26
  def initialize device
11
27
  @device = device
12
28
  @handle = nil
29
+ @polling_frequency = DefaultPollingFrequency
13
30
  end
14
31
 
15
- def self.sparks
32
+ # polling frequency describes how aggressively ruby will ask for new bytes when waiting for the device to print something
33
+ # a lower value is faster (it is in hertz)
34
+ attr_accessor :polling_frequency
35
+
36
+ # Returns an array of all Digisparks connected to this computer. Optionally specify a device name string to return only Digisparks with
37
+ # that name. At the time of writing there is no easy way to customize the device name in the Digispark Arduino software, but hopefully
38
+ # there will be in the future.
39
+ def self.sparks product_name = false
16
40
  usb = LIBUSB::Context.new
17
41
  usb.devices.select { |device|
18
- device.idProduct == ProductID && device.idVendor == VendorID && device.manufacturer == "digistump.com"
42
+ device.idProduct == ProductID && device.idVendor == VendorID && device.manufacturer == "digistump.com" && (product_name == false || product_name.to_s == device.product)
19
43
  }.map { |handle|
20
44
  self.new(handle)
21
45
  }
22
46
  end
23
47
 
24
48
 
25
- # read a single character
49
+ # Attempt to read a single character from the Digispark. Returns a string either zero or one characters long.
50
+ # A zero character string means there are no characters available to read - the Digispark hasn't printed anything for you to consume yet.
51
+ # Returns next time Digispark calls DigiUSB.refresh() regardless of how many characters are available.
26
52
  def getc
27
53
  control_transfer(
28
54
  bRequest: 0x01, # hid get report
@@ -30,7 +56,8 @@ class DigiUSB
30
56
  )
31
57
  end
32
58
 
33
- # write a single character
59
+ # Send a single character in to the Digispark's memory. Argument may be either a single byte String, or an integer between 0 and 255 inclusive.
60
+ # Returns next time Digispark calls DigiUSB.refresh()
34
61
  def putc character
35
62
  character = [character % 256].pack('c') if character.is_a? Integer
36
63
  raise "Cannot putc more than one byte" if character.bytesize > 1
@@ -42,20 +69,29 @@ class DigiUSB
42
69
  )
43
70
  end
44
71
 
45
- # get a string up until the first newline
72
+ # Read a string fromt he Digispark until a newline is received (eg, from the println function in Digispark's DigiUSB library)
73
+ # The returned string includes a newline character on the end.
46
74
  def gets
47
75
  chars = ""
48
- chars += getc() until chars.include? "\n"
76
+ until chars.include? "\n"
77
+ char = getc()
78
+ chars += char
79
+ sleep 1.0 / PollingFrequency if char == ""
80
+ end
49
81
  return chars
50
82
  end
83
+ alias_method :getln, :gets
84
+ alias_method :get_line, :gets
51
85
 
52
- # write a string followed by a newline
86
+ # Send a String to the Digispark followed by a newline.
53
87
  def puts string = ""
54
88
  write "#{string}\n"
55
89
  end
56
90
  alias_method :println, :puts
91
+ alias_method :print_line, :puts
92
+ alias_method :write_line, :puts
57
93
 
58
- # write a string
94
+ # Send a String to the Digispark
59
95
  def write string
60
96
  string.each_byte do |byte|
61
97
  putc byte
@@ -63,20 +99,45 @@ class DigiUSB
63
99
  string
64
100
  end
65
101
  alias_method :print, :write
102
+ alias_method :send, :write
66
103
 
67
- # read a certain number of bytes and return them as a string
104
+ # Recieve a specific number of bytes and return them as a String. Unlike #getc read will wait until
105
+ # the specified number of bytes are available before returning.
68
106
  def read bytes = 1
69
107
  chars = ""
108
+
109
+ until chars.include? "\n"
110
+ char = getc()
111
+ chars += char
112
+ sleep 1.0 / PollingFrequency if char == ""
113
+ end
114
+
70
115
  chars += getc() until chars.length == bytes
71
116
  return chars
72
117
  end
73
118
 
119
+ # A friendly textual representation of this specific Digispark. Can be called without claiming the digispark for this program
74
120
  def inspect
75
- "<Digispark:#{@device.product}:@#{@device.bus_number}.#{@device.device_address}>"
121
+ "<Digispark:#{name}:@#{address}>"
76
122
  end
77
123
  alias_method :to_s, :inspect
78
124
 
125
+ # Return the device name as a String
126
+ def name
127
+ @device.product
128
+ end
129
+
130
+ # Returns the device's bus number and address on the computer's USB interface as a string
131
+ def address
132
+ "#{@device.bus_number}.#{@device.device_address}"
133
+ end
79
134
 
135
+ # Release this Digispark so other programs can read and write to it.
136
+ def close
137
+ @handle.close
138
+ @handle = nil
139
+ end
140
+ alias_method :release, :close
80
141
 
81
142
  private
82
143
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: digiusb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: