digiusb 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: