phidgets_native 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/Gemfile +3 -0
  2. data/Gemfile.lock +12 -0
  3. data/README.rdoc +176 -0
  4. data/Rakefile +31 -0
  5. data/examples/gps.rb +25 -0
  6. data/examples/interface_kit.rb +61 -0
  7. data/examples/lib/common.rb +51 -0
  8. data/examples/lib/console_table.rb +38 -0
  9. data/examples/list_all.rb +16 -0
  10. data/examples/spatial.rb +53 -0
  11. data/ext/phidgets_native/accelerometer_ruby.c +36 -0
  12. data/ext/phidgets_native/advancedservo_ruby.c +33 -0
  13. data/ext/phidgets_native/analog_ruby.c +34 -0
  14. data/ext/phidgets_native/bridge_ruby.c +32 -0
  15. data/ext/phidgets_native/device.c +68 -0
  16. data/ext/phidgets_native/device_ruby.c +404 -0
  17. data/ext/phidgets_native/encoder_ruby.c +34 -0
  18. data/ext/phidgets_native/extconf.rb +18 -0
  19. data/ext/phidgets_native/frequencycounter_ruby.c +32 -0
  20. data/ext/phidgets_native/gps.c +102 -0
  21. data/ext/phidgets_native/gps_ruby.c +212 -0
  22. data/ext/phidgets_native/interfacekit.c +203 -0
  23. data/ext/phidgets_native/interfacekit_ruby.c +507 -0
  24. data/ext/phidgets_native/ir_ruby.c +33 -0
  25. data/ext/phidgets_native/led_ruby.c +33 -0
  26. data/ext/phidgets_native/motorcontrol_ruby.c +32 -0
  27. data/ext/phidgets_native/phidgets_native.c +197 -0
  28. data/ext/phidgets_native/phidgets_native.h +320 -0
  29. data/ext/phidgets_native/phidgets_native_ruby.c +468 -0
  30. data/ext/phidgets_native/phsensor_ruby.c +32 -0
  31. data/ext/phidgets_native/rfid_ruby.c +31 -0
  32. data/ext/phidgets_native/servo_ruby.c +31 -0
  33. data/ext/phidgets_native/spatial.c +168 -0
  34. data/ext/phidgets_native/spatial_ruby.c +533 -0
  35. data/ext/phidgets_native/stepper_ruby.c +32 -0
  36. data/ext/phidgets_native/temperaturesensor_ruby.c +31 -0
  37. data/ext/phidgets_native/textlcd_ruby.c +31 -0
  38. data/ext/phidgets_native/textled_ruby.c +31 -0
  39. data/ext/phidgets_native/weightsensor_ruby.c +32 -0
  40. data/phidgets_native.gemspec +21 -0
  41. metadata +96 -0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rake-compiler'
data/Gemfile.lock ADDED
@@ -0,0 +1,12 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ rake (10.1.0)
5
+ rake-compiler (0.8.3)
6
+ rake
7
+
8
+ PLATFORMS
9
+ ruby
10
+
11
+ DEPENDENCIES
12
+ rake-compiler
data/README.rdoc ADDED
@@ -0,0 +1,176 @@
1
+ =What is PhidgetsNative
2
+ This library is a set of classes for use with the excellent USB sensing and
3
+ controller devices available for sale on phidgets.com. If you're a ruby programmer
4
+ and need to interface your code with meat-space concerns, these devices (and this
5
+ library) are what you need.
6
+
7
+ ==What's a Phidget?
8
+ Phidgets are well supported on almost any operating system, and require practically
9
+ no knowledge of electrical engineering or digital circuitry. Each device is a stand-
10
+ alone "plug and play" building block that works on it's own , or in conjunction
11
+ with other phidgets.
12
+
13
+ You can browse the phidget product catalog on {www.phidgets.com}[http://www.phidgets.com].
14
+
15
+ ==Tested Environments
16
+ As of this writing, this gem is stable, and actively tested on:
17
+ * x86_64 on OS X
18
+ * x86_64 on Linux
19
+ * armv6l on Linux
20
+
21
+ Presumably most other UNIX variants will work just fine. Probably win32/win64
22
+ will not.
23
+
24
+ ==Supported Devices
25
+ As of this version, we currently only support the following phidgets:
26
+ * Phidget Spatial
27
+ * Phidget GPS
28
+ * Phidget Interface Kit
29
+ There will soon be support for the "Phidget Servo" phidget. If you have a phidget
30
+ that's not on our current compatibility list, either get me a copy of the phidget
31
+ to work with at my desk, or check out the existing modules for a reference in
32
+ setting up your own class, and push your changes to my repo. Most of the difficult
33
+ work is done, and you'll find plenty of stubs to work with for nearly all the
34
+ available phidgets.
35
+
36
+ =Why not Phidgets-FFI?
37
+ Though encompassing, Phidgets-FFI is seemingly quite buggy, and a bit slow. Particularly
38
+ with Garbage collection turned on. I think that the threading model of the Phidgets
39
+ C API is simply incompatible with the design of the ruby-ffi library. Additionally,
40
+ running the ffi gem on arm environments is outright unusable.
41
+
42
+ Caveats aside, the Phidgets-FFI library interfaces are elegant and well thought-out,
43
+ and this library's interfaces (and even this README) are heavily influenced by
44
+ them. Converting your existing code base to use this library shouldn't be too
45
+ difficult.
46
+
47
+ ==Differences with Phidgets-FFI
48
+ The Phidgets-FFI library has a number of methods which accept blocks. This library
49
+ has none. Maybe that will change in the future.
50
+
51
+ There are currently no plans to support event-driven interfaces. Though this was
52
+ an excellent feature of the ffi library, it adds a significant degree of complexity
53
+ to a stable implementation of this library. Indeed, most of the stability issues
54
+ arise when attempting to use these features in the ffi implementation.
55
+
56
+ Additionally, the phidgets-ffi implementation is a little strange with it's support
57
+ of device disconnects and reconnects. Here in the 'native' implementation, once
58
+ a device object is created, it stays 'active' regardless of whether the device
59
+ is attached. If the device is disconnected and reconnected, your phidget object
60
+ will automatically re-register its handlers with the device, and continue to
61
+ function as if the device were never disconnected to begin with. Keep in mind that
62
+ any attributes relating to the device's capabilities (mostly those in the
63
+ Phidget::Device class, though there are things like the axial extents in the
64
+ spatial object) will be 'cached' from the previous connection. "State" attributes
65
+ (such as the spatial's accelerometer output) will return nil or 0.
66
+
67
+ In practice, if you need an event-driven model for your code, you can almost certainly
68
+ get by using a ruby thread with a polling loop, like so:
69
+
70
+ is_fixed_last = false
71
+ @poller = Thread.new(Phidget::GPS(12345)) do |gps|
72
+ gps.wait_for_attachment(10000)
73
+
74
+ begin
75
+ on_fixed_change(gps.is_fixed) if is_fixed_last != gps.is_fixed
76
+ is_fixed_last = gps.is_fixed?
77
+ end while sleep(0.1)
78
+ end
79
+
80
+ # Carry on with the rest of your code here
81
+
82
+ I'm fairly certain that until ruby supports actual kernel-based threads, this is
83
+ the best you can reasonably do. Maybe we'll emulate the ffi library in this capacity
84
+ at some point in the future, if there's a demand to do so.
85
+
86
+ =Getting Started
87
+ First, we need to set up the proper environment and get the necessary files off
88
+ the Phidgets website. Visit the drivers section at www.phidgets.com and get the
89
+ latest Phidget driver for your system.
90
+
91
+ We also recommend that you read the following reference materials:
92
+ * {General Phidget Programming}[http://www.phidgets.com/docs/General_Phidget_Programming]
93
+ * The {User Guide}[http://www.phidgets.com/docs/Category:UserGuide] for your device
94
+ * {RubyDoc API Documentation}[http://rubydoc.info/gems/phidgets_native/frames]
95
+ * {Ruby code samples}[https://github.com/kreynolds/phidgets_native/tree/master/examples]
96
+
97
+ The RubyDoc API manual contains calls and events for every type of Phidget and
98
+ can be used as a reference. You can find a high level discussion about programming
99
+ with Phidgets in general on the General Phidget Programming page.
100
+ The user guide for your device also contains an API section that describes
101
+ limitations, defaults, and implementation details specific to your Phidget.
102
+
103
+ ==Installing the phidgets_native gem
104
+ To install:
105
+ gem install phidgets_native
106
+
107
+ phidgets_native is very self contained. There's no dependencies on other ruby
108
+ gems or non-standard libraries. However, in order to compile this gem, you'll
109
+ need a suitable build environment for your system (clang on OSX or gcc on Linux),
110
+ and the aforementioned phidgets driver.
111
+
112
+ ==Coding for your Phidget
113
+ Before you can use the Phidget, you must include a reference to the phidgets_native
114
+ gem:
115
+ require "rubygems"
116
+ require "phidgets_native"
117
+
118
+ Afterwards, Phidgets can be instantiated by creating the appropriate device class
119
+ object, with the device serial number passed to its constructor. At the moment,
120
+ only the 'local' devices are supported. If there's enough interest (or contributors)
121
+ I may add support for the 'remote' protocols which allow you to open a device
122
+ via its computer's IP address.
123
+
124
+ spatial = PhidgetsNative::Spatial.new 54321
125
+
126
+ The object name for any type of Phidget is listed in the API manual. Every type
127
+ of Phidget also inherits functionality from the Phidget base class (Which cannot
128
+ be instantiated by itself directly).
129
+
130
+ If you don't know the serial number of the device you're looking for, you can
131
+ use the Phidget.all method to return an array of the currently connected Phidgets
132
+ and/or you can simply run the included list_all.rb example.
133
+
134
+ One important thing to remember is that when working with Phidgets, a local connection
135
+ will reserve the device until closed. This prevents any other instances from
136
+ retrieving data from the Phidget, including other programs.
137
+
138
+ ==Standard accessors
139
+ All devices support the accessors defined in the Phidget::Device class from which
140
+ they inherit.
141
+
142
+ ==A note about device availability
143
+ Simply calling the constructor does not guarantee you can use the Phidget
144
+ immediately. The constructor merely sets up the Phidget handlers and event hooks,
145
+ but does not block the interpreter while it waits for the device to register.
146
+ For most people, you'll want immediate access to the phidget after the class has
147
+ been instantiated. As such, you'll need to call the wait_for_attachment method
148
+ on your new instance in order to start accessing the device properties.
149
+
150
+ The wait_for_attachment method will block until a connection is made to the
151
+ Phidget or until the provided timeout is exceeded.
152
+
153
+ ifkit = PhidgetsNative::InterfaceKit.new 24680
154
+ # halt the program for up 20000 microseconds or until the Phidget is connected:
155
+ ifkit.wait_for_attachment 20000
156
+
157
+ Though optional, it's recommended that you call close when you're done using your
158
+ phidget or when quitting your program.
159
+
160
+ ifkit.close
161
+
162
+ ==Working with Multiple Phidgets
163
+ Multiple Phidgets of the same or different types can easily be run inside the
164
+ same program. However, there is seemingly a six-device limit, which is imposed
165
+ by the Phidget API and/or hardware.
166
+
167
+ ==Logging
168
+ The phidget api has built in debug logging which can be enabled on a global basis
169
+ for all devices. By default, logs are sent to STDOUT, but you can optionally
170
+ pass a path to a text file where output can alternatively be redirected. You can
171
+ also send your own messages to the logger, if you think you have something you
172
+ need to add.
173
+
174
+ PhidgetsNative.enable_logging!(:verbose)
175
+ PhidgetsNative.log :info, "My favorite color is chartreuse"
176
+ PhidgetsNative.disable_logging!
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ # File: Rakefile
2
+
3
+ require 'rake/extensiontask'
4
+ require 'rake/packagetask'
5
+ require 'rdoc/task'
6
+
7
+ spec = Gem::Specification.load('phidgets_native.gemspec')
8
+
9
+ Rake::ExtensionTask.new 'phidgets_native', spec
10
+
11
+ Gem::PackageTask.new(spec) do |pkg|
12
+
13
+
14
+ end
15
+
16
+ RDOC_FILES = FileList["README.rdoc", "ext/phidgets_native/phidgets_native_ruby.c",
17
+ "ext/phidgets_native/*_ruby.c"]
18
+
19
+ Rake::RDocTask.new do |rd|
20
+ rd.main = "README.rdoc"
21
+ rd.rdoc_dir = "doc/site/api"
22
+ rd.rdoc_files.include(RDOC_FILES)
23
+ end
24
+
25
+ Rake::RDocTask.new(:ri) do |rd|
26
+ rd.main = "README.rdoc"
27
+ rd.rdoc_dir = "doc/ri"
28
+ rd.options << "--ri-system"
29
+ rd.rdoc_files.include(RDOC_FILES)
30
+ end
31
+
data/examples/gps.rb ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require '%s/lib/common' % File.dirname(__FILE__)
5
+
6
+ phidgets_example_for(PhidgetsNative::GPS) do |gps|
7
+ puts "\nPolled Values:"
8
+
9
+ i = 0
10
+ ConsoleTable.new( [
11
+ 'Sample Rate',
12
+ 'Is Fixed',
13
+ '%-18s' % 'Latitude',
14
+ '%-18s' % 'Longitude',
15
+ '%-18s' % 'Altitude',
16
+ 'Heading',
17
+ '%-18s' % 'Velocity',
18
+ '%-23s' % 'Time (UTC)'
19
+ ] ).output(:header => (i == 0), :separator => false) do |columns|
20
+ i+=1
21
+ [ [ '%s Hz' % gps.sample_rate ] + [gps.is_fixed?, gps.latitude,
22
+ gps.longitude, gps.altitude, gps.heading, gps.velocity].collect(&:inspect)+[
23
+ (gps.now_at_utc) ? gps.now_at_utc.strftime("%Y-%m-%d %H:%M:%S.%3N") : nil.inspect ] ]
24
+ end while sleep(3)
25
+ end
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require '%s/lib/common' % File.dirname(__FILE__)
5
+
6
+ #PhidgetsNative.enable_logging! :verbose
7
+
8
+ additional_attribs = [
9
+ %w(Digital\ Inputs input_count),
10
+ %w(Digital\ Outputs output_count),
11
+ %w(Analog\ Inputs sensor_count),
12
+ %w(Change\ Triggers change_triggers),
13
+ %w(Data\ Rates data_rates),
14
+ %w(Data\ Rates\ Min data_rates_min),
15
+ %w(Data\ Rates\ Max data_rates_max)
16
+ ]
17
+
18
+ phidgets_example_for(PhidgetsNative::InterfaceKit, additional_attribs) do |ifkit|
19
+ # Here's how you set digital outputs:
20
+ (0...ifkit.output_count).each{ |i| ifkit.output i, i.even? }
21
+
22
+ # Let's adjust the data rates on each input a bit:
23
+ (0...ifkit.sensor_count).each do |i|
24
+ case (i % 4)
25
+ when 0
26
+ when 1
27
+ ifkit.data_rate i, ifkit.data_rates_max[i]
28
+ when 2
29
+ ifkit.change_trigger i, 1
30
+ when 3
31
+ ifkit.data_rate i, ifkit.data_rates_min[i]
32
+ end
33
+ end
34
+
35
+ # Test sensor_raw
36
+ puts "Raw Analog sensor values:"
37
+ ConsoleTable.new((0...ifkit.sensor_count).collect{|i| "Sensor #{i}"}).output do
38
+ [(0...ifkit.sensor_count).collect{|i| ifkit.sensor_raw(i).inspect } ]
39
+ end
40
+
41
+ puts "\nPolled Values:"
42
+ i = 0
43
+ ConsoleTable.new([
44
+ 'Input Sample Rates',
45
+ 'Sensor Sample Rates',
46
+ 'Ratiometric?',
47
+ '%-40s' % 'sensors',
48
+ '%-20s' % 'inputs',
49
+ '%-20s' % 'outputs'
50
+ ]).output(:header => (i == 0), :separator => false) do |columns|
51
+ i+=1
52
+
53
+ #TODO Test the ratiometric set at some point
54
+
55
+ [ [ifkit.input_sample_rates, ifkit.sensor_sample_rates, ifkit.ratiometric?.inspect,
56
+ ifkit.sensors.inspect]+[ifkit.inputs, ifkit.outputs].collect{ |bools|
57
+ (bools.kind_of? Array) ?
58
+ '[%s]' % bools.collect{|b| (b) ? '1' : '0' }.join(', ') : bools.inspect}
59
+ ]
60
+ end while sleep(3)
61
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+
3
+ $:.push *['%s/../../lib/', '%s'].collect{|p| p % File.dirname(__FILE__) }
4
+
5
+ require 'console_table'
6
+ require 'phidgets_native'
7
+
8
+ # To keep things DRY, I went ahead and put this here:
9
+ def phidgets_example_for(device_klass, extended_attribs = [], &block)
10
+
11
+ serial_number = $1.to_i if ARGV.length == 1 && /\A([\d]+)\Z/.match(ARGV[0])
12
+
13
+ unless serial_number
14
+ puts "Invalid or non-existant device serial number. This is a required parameter"
15
+ puts
16
+ puts "Usage: %s [device_serial]" % File.basename($PROGRAM_NAME)
17
+ exit 1
18
+ end
19
+
20
+ device = device_klass.new serial_number
21
+
22
+ trap("SIGINT"){ device.close; exit }
23
+
24
+ begin
25
+ device.wait_for_attachment 10000
26
+ rescue PhidgetsNative::TimeoutError
27
+ puts "Unable to enumerate the phidget of type %s with the serial number %d." % [
28
+ device.class.to_s, device.serial_number]
29
+ exit
30
+ end
31
+
32
+ puts "Using Library version: "+PhidgetsNative::LIBRARY_VERSION
33
+
34
+ puts "\nDevice Attributes:"
35
+
36
+
37
+ ConsoleTable.new(%w(Attribute Value)).output do
38
+ [ ["Type", device.type.inspect],
39
+ ["Name", device.name.inspect],
40
+ ["Label", device.label.inspect],
41
+ ["Serial", device.serial_number.inspect],
42
+ ["Version", device.version.inspect],
43
+ ["Device class", device.device_class.inspect],
44
+ ["Device id", device.device_id.inspect] ]+extended_attribs.collect{|pairs|
45
+ label, attr = pairs
46
+ [label, device.send(attr.to_sym)]
47
+ }
48
+ end
49
+
50
+ block.call(device)
51
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: UTF-8
2
+
3
+ # Just a quickie hack-class I made to make the test scripts easier to understand
4
+ # and DRY
5
+ class ConsoleTable
6
+ ERR_ROW_LENGTH = "All Rows must have the same number of columns"
7
+
8
+ def initialize(column_labels)
9
+ @columns = column_labels
10
+ end
11
+
12
+ def output(options = {}, &block)
13
+ rows = block.call(@columns)
14
+ if rows.length > 0
15
+ raise StandardError, ERR_ROW_LENGTH if rows.any?{|r| r.length != @columns.length}
16
+
17
+ # Find the widest cell widths:
18
+ widths = ([@columns]+rows).inject(Array.new(@columns.length,0)){|ret, row|
19
+ (0...row.length).collect{|i| (ret[i] >= row[i].to_s.length) ? ret[i] : row[i].to_s.length }
20
+ }
21
+
22
+ # Construct the separator and end_cap rows:
23
+ end_cap, separator = %w(+%s+ |%s|).collect{|fmt|
24
+ fmt % widths.collect{|width| "-" * (width+4) }.join('|')
25
+ }
26
+
27
+ row_fmt = '| %s |' % widths.collect{|width| "%-#{width}s"}.join(' | ')
28
+
29
+ puts [
30
+ (options[:header] == false) ? nil : [ end_cap, row_fmt % @columns, separator],
31
+ rows.to_enum(:each_with_index).collect{ |row,i |
32
+ [ (options[:separator] == false || i == 0) ? nil : separator, row_fmt % row ] },
33
+ (options[:footer] == false) ? nil : end_cap
34
+ ].flatten.compact.join("\n")
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $:.push *['%s/../lib/', '%s/lib/'].collect{|p| p % File.dirname(__FILE__) }
5
+ require 'console_table'
6
+ require 'phidgets_native'
7
+
8
+ PhidgetsNative.enable_logging! :verbose
9
+
10
+ puts "Using Library version: "+PhidgetsNative::LIBRARY_VERSION
11
+
12
+ ConsoleTable.new(%w(Serial\ No. Type Class Name Version)).output do
13
+ PhidgetsNative.all.enum_for(:each_with_index).collect{ |p,i|
14
+ %w(serial_number type device_class name version).collect{|attr| p.send attr}
15
+ }
16
+ end
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require '%s/lib/common' % File.dirname(__FILE__)
5
+
6
+ additional_attribs = [
7
+ %w(Compass\ Correction compass_correction),
8
+ %w(Data\ Rate data_rate),
9
+ %w(Data\ Rate\ Max data_rate_max),
10
+ %w(Data\ Rate\ Min data_rate_min),
11
+ %w(Accelerometer\ Axes accelerometer_axes),
12
+ %w(Accelerometer\ Min accelerometer_min),
13
+ %w(Accelerometer\ Max accelerometer_max),
14
+ %w(Gyroscope\ Axes gyro_axes),
15
+ %w(Gyroscope\ Min gyro_min),
16
+ %w(Gyroscope\ Max gyro_max),
17
+ %w(Compass\ Axes compass_axes),
18
+ %w(Compass\ Min compass_min),
19
+ %w(Compass\ Max compass_max)
20
+ ]
21
+
22
+ phidgets_example_for( PhidgetsNative::Spatial, additional_attribs ) do |spatial|
23
+ # This is worth doing before you start to use a gyro:
24
+ spatial.zero_gyro!
25
+
26
+ # This is worth doing as well:
27
+ spatial.compass_correction = [ 0.441604, 0.045493, 0.176548, 0.002767, 1.994358,
28
+ 2.075937, 2.723117, -0.019360, -0.008005, -0.020036, 0.007017, -0.010891, 0.009283 ]
29
+
30
+ # This is almost never worth doing. I just put it in here for demonstration
31
+ # and test purposes
32
+ spatial.reset_compass_correction!
33
+
34
+ # Probably you'll never need to do this either:
35
+ spatial.data_rate = 16
36
+
37
+ puts "\nPolled Values:"
38
+
39
+ i = 0
40
+ ConsoleTable.new([
41
+ 'Sample Rate',
42
+ '%-40s' % 'Accelerometer',
43
+ '%-40s' % 'Gyroscope',
44
+ '%-40s' % 'Compass'
45
+ ]).output(:header => (i == 0), :separator => false) do |columns|
46
+ i+=1
47
+ [ ['%d Hz' % spatial.sample_rate]+[
48
+ spatial.accelerometer, spatial.gyro, spatial.compass ].collect{ |axes|
49
+ (axes.kind_of? Array) ?
50
+ '[%s]' % axes.collect{|a| '%0.6f' % a}.join(', ') : axes.inspect
51
+ } ]
52
+ end while sleep(3)
53
+ end
@@ -0,0 +1,36 @@
1
+ #include "phidgets_native.h"
2
+
3
+ /*
4
+ * Document-class: PhidgetsNative::Accelerometer < PhidgetsNative::Device
5
+ *
6
+ * This class is a stub, and is currently in need of an actual implementation.
7
+ * Nonetheless, all of the methods from its parent class PhidgetsNative::Device are
8
+ * available.
9
+ */
10
+
11
+ void Init_phidgets_native_accelerometer(VALUE m_Phidget) {
12
+ VALUE c_Device = rb_const_get(m_Phidget, rb_intern("Device"));
13
+
14
+ VALUE c_Accelerometer = rb_define_class_under(m_Phidget, "Accelerometer", c_Device);
15
+
16
+ /*
17
+ * Document-method: new
18
+ * call-seq:
19
+ * new(serial_number)
20
+ *
21
+ * All phidget objects are created from the device serial number. Serial numbers
22
+ * are required to be Fixnums (aka "unsigned integers").
23
+ */
24
+ rb_define_method(c_Accelerometer, "initialize", accelerometer_initialize, 1);
25
+
26
+ }
27
+
28
+ VALUE accelerometer_initialize(VALUE self, VALUE serial) {
29
+ PhidgetInfo *info = device_info(self);
30
+
31
+ CPhidgetAccelerometerHandle accelerometer = 0;
32
+ ensure(CPhidgetAccelerometer_create(&accelerometer));
33
+
34
+ info->handle = (CPhidgetHandle)accelerometer;
35
+ return rb_call_super(1, &serial);
36
+ }
@@ -0,0 +1,33 @@
1
+ #include "phidgets_native.h"
2
+
3
+ /*
4
+ * Document-class: PhidgetsNative::AdvancedServo < PhidgetsNative::Device
5
+ *
6
+ * This class is a stub, and is currently in need of an actual implementation.
7
+ * Nonetheless, all of the methods from its parent class PhidgetsNative::Device are
8
+ * available.
9
+ */
10
+
11
+ void Init_phidgets_native_advancedservo(VALUE m_Phidget) {
12
+ VALUE c_Device = rb_const_get(m_Phidget, rb_intern("Device"));
13
+
14
+ VALUE c_AdvancedServo = rb_define_class_under(m_Phidget, "AdvancedServo", c_Device);
15
+
16
+ /*
17
+ * Document-method: new
18
+ * call-seq:
19
+ * new(serial_number)
20
+ *
21
+ * All phidget objects are created from the device serial number. Serial numbers
22
+ * are required to be Fixnums (aka "unsigned integers").
23
+ */
24
+ rb_define_method(c_AdvancedServo, "initialize", advancedservo_initialize, 1);
25
+ }
26
+
27
+ VALUE advancedservo_initialize(VALUE self, VALUE serial) {
28
+ PhidgetInfo *info = device_info(self);
29
+ CPhidgetAdvancedServoHandle advancedservo = 0;
30
+ ensure(CPhidgetAdvancedServo_create(&advancedservo));
31
+ info->handle = (CPhidgetHandle)advancedservo;
32
+ return rb_call_super(1, &serial);
33
+ }
@@ -0,0 +1,34 @@
1
+ #include "phidgets_native.h"
2
+
3
+ /*
4
+ * Document-class: PhidgetsNative::Analog < PhidgetsNative::Device
5
+ *
6
+ * This class is a stub, and is currently in need of an actual implementation.
7
+ * Nonetheless, all of the methods from its parent class PhidgetsNative::Device are
8
+ * available.
9
+ */
10
+
11
+ void Init_phidgets_native_analog(VALUE m_Phidget) {
12
+ VALUE c_Device = rb_const_get(m_Phidget, rb_intern("Device"));
13
+
14
+ VALUE c_Analog = rb_define_class_under(m_Phidget, "Analog", c_Device);
15
+
16
+ /*
17
+ * Document-method: new
18
+ * call-seq:
19
+ * new(serial_number)
20
+ *
21
+ * All phidget objects are created from the device serial number. Serial numbers
22
+ * are required to be Fixnums (aka "unsigned integers").
23
+ */
24
+ rb_define_method(c_Analog, "initialize", analog_initialize, 1);
25
+ }
26
+
27
+
28
+ VALUE analog_initialize(VALUE self, VALUE serial) {
29
+ PhidgetInfo *info = device_info(self);
30
+ CPhidgetAnalogHandle analog = 0;
31
+ ensure(CPhidgetAnalog_create(&analog));
32
+ info->handle = (CPhidgetHandle)analog;
33
+ return rb_call_super(1, &serial);
34
+ }
@@ -0,0 +1,32 @@
1
+ #include "phidgets_native.h"
2
+
3
+ /*
4
+ * Document-class: PhidgetsNative::Bridge < PhidgetsNative::Device
5
+ *
6
+ * This class is a stub, and is currently in need of an actual implementation.
7
+ * Nonetheless, all of the methods from its parent class PhidgetsNative::Device are
8
+ * available.
9
+ */
10
+ void Init_phidgets_native_bridge(VALUE m_Phidget) {
11
+ VALUE c_Device = rb_const_get(m_Phidget, rb_intern("Device"));
12
+
13
+ VALUE c_Bridge = rb_define_class_under(m_Phidget, "Bridge", c_Device);
14
+
15
+ /*
16
+ * Document-method: new
17
+ * call-seq:
18
+ * new(serial_number)
19
+ *
20
+ * All phidget objects are created from the device serial number. Serial numbers
21
+ * are required to be Fixnums (aka "unsigned integers").
22
+ */
23
+ rb_define_method(c_Bridge, "initialize", bridge_initialize, 1);
24
+ }
25
+
26
+ VALUE bridge_initialize(VALUE self, VALUE serial) {
27
+ PhidgetInfo *info = device_info(self);
28
+ CPhidgetBridgeHandle bridge = 0;
29
+ ensure(CPhidgetBridge_create(&bridge));
30
+ info->handle = (CPhidgetHandle)bridge;
31
+ return rb_call_super(1, &serial);
32
+ }
@@ -0,0 +1,68 @@
1
+ #include "phidgets_native.h"
2
+
3
+ PhidgetInfo *device_info(VALUE self) {
4
+ PhidgetInfo *info;
5
+ Data_Get_Struct( self, PhidgetInfo, info );
6
+
7
+ return info;
8
+ }
9
+
10
+ void *device_type_info(VALUE self) {
11
+ PhidgetInfo *info;
12
+ Data_Get_Struct( self, PhidgetInfo, info );
13
+
14
+ return info->type_info;
15
+ }
16
+
17
+ int CCONV device_on_attach(CPhidgetHandle phid, void *userptr)
18
+ {
19
+ int serialNo;
20
+ report(CPhidget_getSerialNumber(phid, &serialNo));
21
+
22
+ // Populate our data structures with what we know about this device:
23
+ PhidgetInfo *info = userptr;
24
+ info->is_attached = true;
25
+
26
+ gettimeofday(&info->attached_at, &info->attached_at_tz);
27
+
28
+ // Phidget Attributes:
29
+ report(CPhidget_getDeviceType(phid, &info->type));
30
+ report(CPhidget_getDeviceVersion(phid, &info->version));
31
+ report(CPhidget_getDeviceClass(phid, &info->device_class));
32
+ report(CPhidget_getDeviceID(phid, &info->device_id));
33
+ report(CPhidget_getDeviceLabel(phid, &info->label));
34
+ report(CPhidget_getDeviceName(phid, &info->name));
35
+
36
+ return (info->on_type_attach) ? (*info->on_type_attach)(phid, info) : 0;
37
+ }
38
+
39
+ int CCONV device_on_detach(CPhidgetHandle phid, void *userptr) {
40
+ int serialNo;
41
+ report(CPhidget_getSerialNumber(phid, &serialNo));
42
+
43
+ PhidgetInfo *info = userptr;
44
+ info->is_attached = false;
45
+
46
+ return (info->on_type_detach) ? (*info->on_type_detach)(phid, info) : 0;
47
+ }
48
+
49
+ int CCONV device_on_error(CPhidgetHandle phid, void *userptr, int ErrorCode, const char *unknown) {
50
+ CPhidget_log(PHIDGET_LOG_ERROR, "N/A", "PhidgetNative OnError: %s", unknown);
51
+ return 0;
52
+ }
53
+
54
+ void device_free(PhidgetInfo *info) {
55
+ if (info) {
56
+ if (info->handle) {
57
+ report(CPhidget_close((CPhidgetHandle)info->handle));
58
+ report(CPhidget_delete((CPhidgetHandle)info->handle));
59
+ }
60
+
61
+ if (info->on_type_free)
62
+ (*info->on_type_free)(info->type_info);
63
+
64
+ if (info)
65
+ xfree(info);
66
+ }
67
+ }
68
+