minilab 2.0.0-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +2 -0
- data/.gitignore +2 -0
- data/CHANGES +22 -0
- data/Gemfile +3 -0
- data/LICENSE +19 -0
- data/README.rdoc +101 -0
- data/Rakefile +25 -0
- data/doc/UniLib.chm +0 -0
- data/doc/minilab-1008.pdf +0 -0
- data/doc/minilab_systest_setup.txt +38 -0
- data/doc/port_mapping.txt +2 -0
- data/lib/minilab/analog_io.rb +25 -0
- data/lib/minilab/connection_state.rb +15 -0
- data/lib/minilab/digital_auxport_io.rb +36 -0
- data/lib/minilab/digital_configuration.rb +55 -0
- data/lib/minilab/digital_port_io.rb +41 -0
- data/lib/minilab/library_translator.rb +48 -0
- data/lib/minilab/minilab.rb +130 -0
- data/lib/minilab/minilab_constants.rb +22 -0
- data/lib/minilab/minilab_context.rb +18 -0
- data/lib/minilab/minilab_hardware.rb +118 -0
- data/lib/minilab/minilab_wrapper.rb +14 -0
- data/lib/minilab/objects.yml +24 -0
- data/lib/minilab/version.rb +3 -0
- data/lib/minilab.rb +14 -0
- data/minilab.gemspec +32 -0
- data/spec/acceptance/analog_spec.rb +35 -0
- data/spec/acceptance/digital_port_spec.rb +81 -0
- data/spec/acceptance/digital_screw_terminal_spec.rb +22 -0
- data/spec/spec_helper.rb +102 -0
- data/spec/unit/analog_io_spec.rb +55 -0
- data/spec/unit/connection_state_spec.rb +14 -0
- data/spec/unit/digital_auxport_io_spec.rb +98 -0
- data/spec/unit/digital_configuration_spec.rb +96 -0
- data/spec/unit/digital_port_io_spec.rb +65 -0
- data/spec/unit/library_translator_spec.rb +86 -0
- data/spec/unit/minilab_context_spec.rb +17 -0
- data/spec/unit/minilab_hardware_spec.rb +17 -0
- data/spec/unit/minilab_spec.rb +104 -0
- data/spec/unit/minilab_wrapper_spec.rb +20 -0
- data/vendor/mcc/cbw32.dll +0 -0
- metadata +192 -0
data/.document
ADDED
data/.gitignore
ADDED
data/CHANGES
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
== 2.0.0
|
2
|
+
* minilab now requires Ruby 1.9 to run and is built for the RubyInstaller package.
|
3
|
+
minilab's public interface has not changed.
|
4
|
+
* Now using the latest and greatest bundler techniques for gem development.
|
5
|
+
* Two libraries minilab used for testing (hardmock and systir) do not run on Ruby 1.9. Therefore, minilab now uses:
|
6
|
+
** RSpec as a test harness
|
7
|
+
** steak as an acceptance test harness
|
8
|
+
** rr for mocking in unit tests
|
9
|
+
|
10
|
+
== 1.1.1
|
11
|
+
* Lots of little things changed as part of the Rubyforge -> Gemcutter/GitHub/rdoc.info migration
|
12
|
+
minilab's public interface has not changed.
|
13
|
+
* Using bundler to package what gems.
|
14
|
+
|
15
|
+
== 1.1.0
|
16
|
+
* Conversion from native extension to FFI
|
17
|
+
* Upgraded diy, constructor, and hardmock to their latest versions
|
18
|
+
* Internal implementation changes. minilab's public interface is unchanged
|
19
|
+
* Integration tests removed, as the value they provide did not outweigh the maintenance burden
|
20
|
+
|
21
|
+
== 1.0.0
|
22
|
+
First release
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2007-2011 Atomic Object LLC
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
== About
|
2
|
+
|
3
|
+
minilab is a Ruby library for Measurement Computing's miniLAB 1008 device. The minilab library provides a simple interface to several of the miniLAB 1008's analog and digital IO functions. I've used the miniLAB to control the input and examine the output from our embedded devices; the minilab library allowed us to use automated system testing tools for Ruby.
|
4
|
+
|
5
|
+
minilab does not work with other Measurement Computing devices, but could be extended to do so.
|
6
|
+
|
7
|
+
=== Ruby 1.9
|
8
|
+
The minilab gem now requires Ruby 1.9 to run. The gem is built to run on the RubyInstaller package. minilab's public interface has not changed as part of the Ruby 1.9 migration.
|
9
|
+
|
10
|
+
If you're looking for Ruby 1.8 support, try using the 1.1.0 version of the gem. The code is available in the git repository via the v1.1.0 tag.
|
11
|
+
|
12
|
+
== Installation
|
13
|
+
|
14
|
+
1. Install the minilab gem onto your system or unpack it into a local directory in your project. Install Measurement Computing's Universal Library and InstaCal software; both come on CDs with the device.
|
15
|
+
|
16
|
+
1. Plug in the device and then fire up the InstaCal software. Go to Install -> Configure in the menus and the Custom Serial Number to 253, No. of Channels to 8 Single Ended, and Trigger Source to DIO0. Use the Flash LED button to ensure that InstaCal can communicate with the device (I've never had a problem with this). Although I don't think the Custom Serial Number and Trigger Source make much difference to my library, the No. of Channels is important (see Known limitations below).
|
17
|
+
|
18
|
+
1. That should be it---you should now be able to require 'minilab', create a minilab object, and connect to it. If you can't, please contact me! I've only installed this on a limited number of computers, so I'd like to hear about problems with the library installation, gem installation, LOAD_PATH, etc.
|
19
|
+
|
20
|
+
== Usage
|
21
|
+
=== Build and connect
|
22
|
+
|
23
|
+
First you'll need to build the Minilab object; use the +Minilab.build+ method to do this. The method is important to use instead of +new+, since it takes care of a lot of behind-the-scenes object construction for you.
|
24
|
+
|
25
|
+
After building the object, use the +connect+ method. This will establish the connection to the library. None of the other methods will work until you connect.
|
26
|
+
|
27
|
+
Example:
|
28
|
+
|
29
|
+
minilab = Minilab.build
|
30
|
+
minilab.connect
|
31
|
+
|
32
|
+
=== Reading and writing data
|
33
|
+
|
34
|
+
I've created methods for reading and writing both digital and analog data from the device. Analog data goes through the read and write pins on the top of the device; no configuration is needed for the analog methods.
|
35
|
+
|
36
|
+
Digital data goes through either the DIO pins on the top of the device or the digital ports on the DB37 port. If you're using the DIO pins, then you don't need to do any configuration. If you're using the DB37 pins, then you'll need to configure the appropriate port for input and output. You can find a mapping of DB37 pin numbers to ports either in Measurement Computing's miniLAB 1008 data sheet or at the end of this README.
|
37
|
+
|
38
|
+
Check out the read and write analog and read, write, and configure digital methods in the Minilab document for more information.
|
39
|
+
|
40
|
+
Example:
|
41
|
+
|
42
|
+
minilab.configure_input_port(:portb)
|
43
|
+
value = minilab.read_digital_byte(:portb)
|
44
|
+
assert_equal 12, value, "wrong value read for system time"
|
45
|
+
|
46
|
+
The adventurous may also want to look at the included acceptance tests for the device, since they are examples of how to use the device and are not contrived.
|
47
|
+
|
48
|
+
== Tests
|
49
|
+
|
50
|
+
The minilab library comes with unit and acceptance tests. The unit tests stress individual units and can run without any hardware plugged in. The acceptance tests represent real use cases for the software when plugged into hardware.
|
51
|
+
|
52
|
+
See the end of this document for an outline of how a miniLAB and DB37 connector should be set up in order to run the system tests.
|
53
|
+
|
54
|
+
== Known limitations
|
55
|
+
|
56
|
+
* Ruby 1.8 is no longer supported.
|
57
|
+
|
58
|
+
* The minilab library only supports one device plugged in at a time. I could add support for multiple devices, but since I only have one, I haven't bothered adding support for more than one.
|
59
|
+
|
60
|
+
* I never got around to writing out an entire digital byte because I never needed it.
|
61
|
+
|
62
|
+
* Reading analog values only supports single-ended mode. As you can probably guess, I didn't need differential mode, so I didn't add support for it.
|
63
|
+
|
64
|
+
== Contact information
|
65
|
+
* Matt Fletcher <fletcher@atomicobject.com>
|
66
|
+
* Atomic Object <http://atomicobject.com>
|
67
|
+
|
68
|
+
== Appendix
|
69
|
+
=== DB37 pin to port mapping
|
70
|
+
Pin:: Port
|
71
|
+
30-37:: :porta
|
72
|
+
3-10:: :portb
|
73
|
+
26-29:: :portcl
|
74
|
+
22-25:: :portch
|
75
|
+
|
76
|
+
=== System test setup
|
77
|
+
|
78
|
+
On top of the miniLAB:
|
79
|
+
CH0 IN:: D/A OUT 1
|
80
|
+
CH1 IN:: GND
|
81
|
+
CH2 IN:: DIO0
|
82
|
+
CH4 IN:: PC 5V
|
83
|
+
CH6 IN:: D/A OUT 0
|
84
|
+
DIO0:: DIO3
|
85
|
+
DIO1:: PC 5V
|
86
|
+
DIO2:: GND
|
87
|
+
|
88
|
+
On the DB37 pins:
|
89
|
+
3:: 11
|
90
|
+
4:: 11
|
91
|
+
5:: 28
|
92
|
+
6:: 11
|
93
|
+
7:: 36
|
94
|
+
8:: 11
|
95
|
+
9:: 11
|
96
|
+
10:: 20
|
97
|
+
22:: 27
|
98
|
+
23:: 21
|
99
|
+
24:: 34
|
100
|
+
25:: 21
|
101
|
+
30:: 21
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "rake/rdoctask"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
desc "Run the unit specs"
|
5
|
+
task :default => "spec:unit"
|
6
|
+
|
7
|
+
namespace :spec do
|
8
|
+
RSpec::Core::RakeTask.new(:unit) do |t|
|
9
|
+
t.pattern = "spec/unit/**/*_spec.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec::Core::RakeTask.new(:acceptance) do |t|
|
13
|
+
t.pattern = "spec/acceptance/**/*_spec.rb"
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "all tests"
|
17
|
+
task :all => %w[ spec:unit spec:acceptance ]
|
18
|
+
end
|
19
|
+
|
20
|
+
Rake::RDocTask.new do |rdoc|
|
21
|
+
rdoc.rdoc_dir = "rdoc"
|
22
|
+
rdoc.title = "minilab: Ruby library for the miniLAB 1008"
|
23
|
+
rdoc.options = %w[ --main README.rdoc --title minilab ]
|
24
|
+
rdoc.rdoc_files.include("lib/minilab.rb", "README.rdoc", "CHANGES", "LICENSE")
|
25
|
+
end
|
data/doc/UniLib.chm
ADDED
Binary file
|
Binary file
|
@@ -0,0 +1,38 @@
|
|
1
|
+
Setting up new Minilab hardware:
|
2
|
+
1) Get it out of the packaging.
|
3
|
+
2) Install the Minilab software (InstaCal, universal library are most important).
|
4
|
+
3) Plug in the Minilab
|
5
|
+
4) Fire up the InstaCal software. Configure the board:
|
6
|
+
- Custom Serial No. 253
|
7
|
+
- No. Of Channels 8 Single Ended
|
8
|
+
- Trigger Source DIO0
|
9
|
+
This configuration should work with the config file I have in the minilab driver
|
10
|
+
directories.
|
11
|
+
5) Wire up the minilab. Use the below wiring:
|
12
|
+
|
13
|
+
On top of the minilab:
|
14
|
+
CH0 IN <---> D/A OUT 1
|
15
|
+
CH1 IN <---> GND
|
16
|
+
CH2 IN <---> DIO0
|
17
|
+
CH4 IN <---> PC +5V
|
18
|
+
CH6 IN <---> D/A OUT 0
|
19
|
+
DIO0 <---> DIO3
|
20
|
+
DIO1 <---> PC +5V
|
21
|
+
DIO2 <---> GND
|
22
|
+
|
23
|
+
On the external digital IO pins:
|
24
|
+
3 <---> 11
|
25
|
+
4 <---> 11
|
26
|
+
5 <---> 28
|
27
|
+
6 <---> 11
|
28
|
+
7 <---> 36
|
29
|
+
8 <---> 11
|
30
|
+
9 <---> 11
|
31
|
+
10 <---> 20
|
32
|
+
22 <---> 27
|
33
|
+
23 <---> 21
|
34
|
+
24 <---> 34
|
35
|
+
25 <---> 21
|
36
|
+
30 <---> 21
|
37
|
+
|
38
|
+
6) Getrdone.
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Minilab
|
2
|
+
class AnalogIo #:nodoc:
|
3
|
+
constructor :minilab_wrapper
|
4
|
+
|
5
|
+
def read_analog(channel)
|
6
|
+
check_channel_range(channel, 0, 7)
|
7
|
+
@minilab_wrapper.read_analog(channel)
|
8
|
+
end
|
9
|
+
|
10
|
+
def write_analog(channel, volts)
|
11
|
+
check_channel_range(channel, 0, 1)
|
12
|
+
|
13
|
+
unless (0.0 .. 5.0) === volts
|
14
|
+
raise "#{volts} volts is out of range for this device; Only voltage between 0.0 and 5.0 is supported."
|
15
|
+
end
|
16
|
+
|
17
|
+
@minilab_wrapper.write_analog(channel, volts)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def check_channel_range(channel, low, high)
|
22
|
+
raise "Channel #{channel} is out of range." unless (low..high) === channel
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Minilab
|
2
|
+
class DigitalAuxportIo #:nodoc:
|
3
|
+
constructor :minilab_wrapper
|
4
|
+
include MinilabConstants
|
5
|
+
|
6
|
+
VALID_PINS = %w[ DIO0 DIO1 DIO2 DIO3 ]
|
7
|
+
|
8
|
+
def read_digital(pin)
|
9
|
+
validate_pin(pin)
|
10
|
+
configuration = {:direction => DIGITALIN, :pin => get_pin_number(pin)}
|
11
|
+
|
12
|
+
@minilab_wrapper.configure_auxport(configuration)
|
13
|
+
@minilab_wrapper.read_auxport(get_pin_number(pin))
|
14
|
+
end
|
15
|
+
|
16
|
+
def write_digital(pin, value)
|
17
|
+
raise "#{value} is not a valid digital output." if (value < 0)
|
18
|
+
value = 1 if (value > 0)
|
19
|
+
|
20
|
+
validate_pin(pin)
|
21
|
+
configuration = { :direction => DIGITALOUT, :pin => get_pin_number(pin)}
|
22
|
+
|
23
|
+
@minilab_wrapper.configure_auxport(configuration)
|
24
|
+
@minilab_wrapper.write_auxport(get_pin_number(pin), value)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def validate_pin(pin)
|
29
|
+
raise "#{pin} is not a valid digital IO pin" unless VALID_PINS.include?(pin.to_s.upcase)
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_pin_number(pin)
|
33
|
+
pin.match(/(\d)$/)[0].to_i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Minilab
|
2
|
+
class DigitalConfiguration #:nodoc:
|
3
|
+
include MinilabConstants
|
4
|
+
constructor :minilab_wrapper
|
5
|
+
|
6
|
+
PORTS = [:porta, :portb, :portcl, :portch]
|
7
|
+
LIBRARY_PORT_NAMES = {
|
8
|
+
:porta => FIRSTPORTA,
|
9
|
+
:portb => FIRSTPORTB,
|
10
|
+
:portcl => FIRSTPORTCL,
|
11
|
+
:portch => FIRSTPORTCH
|
12
|
+
}
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@port_status = PORTS.inject({}) do |port_status, port|
|
16
|
+
port_status[port] = :not_configured
|
17
|
+
port_status
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure_port_for_input(port)
|
22
|
+
configure_port(port, DIGITALIN)
|
23
|
+
end
|
24
|
+
|
25
|
+
def configure_port_for_output(port)
|
26
|
+
configure_port(port, DIGITALOUT)
|
27
|
+
end
|
28
|
+
|
29
|
+
def is_port_configured_for_input?(port)
|
30
|
+
check_port_status(port, DIGITALIN)
|
31
|
+
end
|
32
|
+
|
33
|
+
def is_port_configured_for_output?(port)
|
34
|
+
check_port_status(port, DIGITALOUT)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def is_port_recognized?(port)
|
39
|
+
raise "Port #{port} is not valid." unless PORTS.include?(port)
|
40
|
+
end
|
41
|
+
|
42
|
+
def configure_port(port, direction)
|
43
|
+
is_port_recognized?(port)
|
44
|
+
|
45
|
+
@minilab_wrapper.configure_port(:direction => direction, :port => LIBRARY_PORT_NAMES[port])
|
46
|
+
@port_status[port] = direction
|
47
|
+
true
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_port_status(port, status)
|
51
|
+
is_port_recognized?(port)
|
52
|
+
@port_status[port] == status ? true : false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Minilab
|
2
|
+
class DigitalPortIo #:nodoc:
|
3
|
+
constructor :minilab_wrapper, :digital_configuration, :library_translator
|
4
|
+
|
5
|
+
def configure_input_port(port)
|
6
|
+
@digital_configuration.configure_port_for_input(port)
|
7
|
+
end
|
8
|
+
|
9
|
+
def configure_output_port(port)
|
10
|
+
@digital_configuration.configure_port_for_output(port)
|
11
|
+
end
|
12
|
+
|
13
|
+
def read_digital(pin)
|
14
|
+
check_pin_configuration(pin, :input)
|
15
|
+
@minilab_wrapper.read_digital_pin(get_library_pin_number(pin))
|
16
|
+
end
|
17
|
+
|
18
|
+
def write_digital(pin, value)
|
19
|
+
check_pin_configuration(pin, :output)
|
20
|
+
@minilab_wrapper.write_digital_pin(get_library_pin_number(pin), value)
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def read_port(port)
|
25
|
+
raise "Digital port #{port} is not configured for input." unless @digital_configuration.is_port_configured_for_input?(port)
|
26
|
+
@minilab_wrapper.read_port(@library_translator.get_library_port(port))
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def get_library_pin_number(pin)
|
31
|
+
@library_translator.get_library_pin_number(pin)
|
32
|
+
end
|
33
|
+
|
34
|
+
def check_pin_configuration(pin, type)
|
35
|
+
port = @library_translator.get_port_for_pin(pin)
|
36
|
+
unless @digital_configuration.send("is_port_configured_for_#{type}?", port)
|
37
|
+
raise "Digital port #{port} for pin #{pin} is not configured for #{type}."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Minilab
|
2
|
+
class LibraryTranslator #:nodoc:
|
3
|
+
include MinilabConstants
|
4
|
+
|
5
|
+
def get_port_for_pin(pin)
|
6
|
+
case pin
|
7
|
+
when 30..37
|
8
|
+
:porta
|
9
|
+
when 3..10
|
10
|
+
:portb
|
11
|
+
when 26..29
|
12
|
+
:portcl
|
13
|
+
when 22..25
|
14
|
+
:portch
|
15
|
+
else
|
16
|
+
raise "Pin #{pin} does not map to a known minilab DB37 port."
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_library_pin_number(pin)
|
21
|
+
case pin
|
22
|
+
when 30..37 # port a pins
|
23
|
+
7 - (pin - 30)
|
24
|
+
when 3..10 # port b pins
|
25
|
+
15 - (pin - 3)
|
26
|
+
when 26..29 # port cl pins
|
27
|
+
19 - (pin - 26)
|
28
|
+
when 22..25 # port ch pins
|
29
|
+
23 - (pin - 22)
|
30
|
+
else
|
31
|
+
raise "Pin #{pin} does not map to a minilab library pin number."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_library_port(port)
|
36
|
+
port_to_library_port_mapping = {
|
37
|
+
:porta => FIRSTPORTA,
|
38
|
+
:portb => FIRSTPORTB,
|
39
|
+
:portcl => FIRSTPORTCL,
|
40
|
+
:portch => FIRSTPORTCH
|
41
|
+
}
|
42
|
+
|
43
|
+
library_port = port_to_library_port_mapping[port]
|
44
|
+
return library_port unless library_port.nil?
|
45
|
+
raise "Port #{port} is not a valid port."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Minilab
|
2
|
+
# Use this method to construct Minilab objects. The object will not yet
|
3
|
+
# be connected to the device.
|
4
|
+
def self.build
|
5
|
+
MinilabContext.new.build[:minilab]
|
6
|
+
end
|
7
|
+
|
8
|
+
# The main interface to the minilab library. Create one of these objects
|
9
|
+
# using the +Minilab.build+ method. After you've created a minilab object,
|
10
|
+
# use the +connect+ method to establish the connection to the device.
|
11
|
+
# Minilab objects are not usable until they've been connected.
|
12
|
+
class Minilab
|
13
|
+
include MinilabConstants
|
14
|
+
constructor :minilab_wrapper, :analog_io, :digital_auxport_io, :digital_port_io, :connection_state
|
15
|
+
|
16
|
+
# Connect to the device. There are two side effects of connecting.
|
17
|
+
# * Error reporting from MCC's universal library is set to print
|
18
|
+
# errors to standard out instead of popping up a Windows dialog.
|
19
|
+
# * Each of the DB37 digital ports is setup for input.
|
20
|
+
def connect
|
21
|
+
@minilab_wrapper.setup_error_handling(DONTPRINT, STOPALL)
|
22
|
+
@minilab_wrapper.declare_revision(CURRENTREVNUM)
|
23
|
+
@connection_state.connected = true
|
24
|
+
DigitalConfiguration::PORTS.each { |port| configure_input_port(port) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Read from one of the eight analog channels (0 - 7) on top of the device.
|
28
|
+
#
|
29
|
+
# Single-ended mode is the only analog mode supported.
|
30
|
+
#
|
31
|
+
# An error is raised if an invalid channel number is given.
|
32
|
+
def read_analog(channel)
|
33
|
+
ensure_connected_to_device
|
34
|
+
@analog_io.read_analog(channel)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Output a voltage on one of the eight analog channels. The output voltage
|
38
|
+
# must be in the range of 0.0 - 5.0 volts.
|
39
|
+
#
|
40
|
+
# Single-ended mode is the only analog mode supported.
|
41
|
+
#
|
42
|
+
# An error is raised if an invalid channel number or an out-of-range
|
43
|
+
# voltage is given.
|
44
|
+
def write_analog(channel, volts)
|
45
|
+
ensure_connected_to_device
|
46
|
+
@analog_io.write_analog(channel, volts)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Configure one of the DB37 ports for input.
|
50
|
+
#
|
51
|
+
# Specify _port_ as a symbol. The available ports are <tt>:porta</tt>,
|
52
|
+
# <tt>:portb</tt>, <tt>:portcl</tt>, and <tt>:portch</tt>. An error is
|
53
|
+
# raised if an invalid port is given.
|
54
|
+
def configure_input_port(port)
|
55
|
+
ensure_connected_to_device
|
56
|
+
@digital_port_io.configure_input_port(port)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Configure one of the DB37 ports for output.
|
60
|
+
#
|
61
|
+
# Specify _port_ as a symbol. The available ports are <tt>:porta</tt>,
|
62
|
+
# <tt>:portb</tt>, <tt>:portcl</tt>, and <tt>:portch</tt>. An error is
|
63
|
+
# raised if an invalid port is given.
|
64
|
+
def configure_output_port(port)
|
65
|
+
ensure_connected_to_device
|
66
|
+
@digital_port_io.configure_output_port(port)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Read a single bit from one of the digital pins.
|
70
|
+
#
|
71
|
+
# If you'd like to read from one of the pins on the top of the device (the
|
72
|
+
# auxport pins), then specify the pin as a string with its label (e.g.
|
73
|
+
# read_digital("DIO1")). Alternatively, if you'd like to read from one of
|
74
|
+
# the DB37 pins, specify the pin as the number it's labeled with (e.g.
|
75
|
+
# read_digital(13)).
|
76
|
+
#
|
77
|
+
# An error is raised if you specify a pin that doesn't exist or if you
|
78
|
+
# try to read from a DB37 pin on a port that is not configured for input.
|
79
|
+
# The digital pins on the top of the device do not need to be configured.
|
80
|
+
def read_digital(pin)
|
81
|
+
ensure_connected_to_device
|
82
|
+
perform_digital_op(pin, :read, pin)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Write a single bit to one of the digital pins. _value_ must be an integer
|
86
|
+
# 1 or 0.
|
87
|
+
#
|
88
|
+
# If you'd like to write to one of the pins on the top of the device (the
|
89
|
+
# auxport pins), then specify the pin as a string with its label (e.g.
|
90
|
+
# write_digital("DIO2", 0)). Alternatively, if you'd like to write to one
|
91
|
+
# of the DB37 pins, specify the pin as the number it's labeled with (e.g.
|
92
|
+
# write_digital(17, 1)).
|
93
|
+
#
|
94
|
+
# An error is raised if you specify a pin that doesn't exist or if you
|
95
|
+
# try to write to a DB37 pin on a port that is not configured for output.
|
96
|
+
# The digital pins on the top of the device do not need to be configured.
|
97
|
+
#
|
98
|
+
# Values above 1 are interpreted as 1; negative values raise an error.
|
99
|
+
def write_digital(pin, value)
|
100
|
+
ensure_connected_to_device
|
101
|
+
perform_digital_op(pin, :write, pin, value)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Read a byte from one of the DB37 ports.
|
105
|
+
#
|
106
|
+
# Specify _port_ as a symbol. The available ports are <tt>:porta</tt>,
|
107
|
+
# <tt>:portb</tt>, <tt>:portcl</tt>, and <tt>:portch</tt>.
|
108
|
+
#
|
109
|
+
# An error is raised if an invalid port is given.
|
110
|
+
def read_digital_byte(port)
|
111
|
+
ensure_connected_to_device
|
112
|
+
@digital_port_io.read_port(port)
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
def perform_digital_op(pin, op, *args)
|
117
|
+
method = "#{op.to_s}_digital"
|
118
|
+
case pin
|
119
|
+
when String
|
120
|
+
@digital_auxport_io.send(method,*args)
|
121
|
+
when Fixnum
|
122
|
+
@digital_port_io.send(method,*args)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def ensure_connected_to_device
|
127
|
+
raise "Cannot use any minilab methods without calling 'connect' first." unless @connection_state.connected?
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Lifted from cbw.h. Let's hope these don't change often.
|
2
|
+
# Using revision number 5.90.
|
3
|
+
module Minilab
|
4
|
+
module MinilabConstants
|
5
|
+
CURRENTREVNUM = 5.90
|
6
|
+
|
7
|
+
BOARDNUM = 0
|
8
|
+
DONTPRINT = 0
|
9
|
+
STOPALL = 2
|
10
|
+
ERRSTRLEN = 256
|
11
|
+
BIP10VOLTS = 1
|
12
|
+
UNI5VOLTS = 101
|
13
|
+
|
14
|
+
AUXPORT = 1
|
15
|
+
DIGITALOUT = 1
|
16
|
+
DIGITALIN = 2
|
17
|
+
FIRSTPORTA = 10
|
18
|
+
FIRSTPORTB = 11
|
19
|
+
FIRSTPORTCL = 12
|
20
|
+
FIRSTPORTCH = 13
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "diy"
|
2
|
+
require "yaml"
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
module Minilab
|
6
|
+
class MinilabContext #:nodoc:
|
7
|
+
OBJECT_DEFINITION = Pathname.new(__FILE__).dirname + "objects.yml"
|
8
|
+
|
9
|
+
def build
|
10
|
+
if not @context
|
11
|
+
DIY::Context.auto_require = false
|
12
|
+
@context = DIY::Context.new(YAML.load_file(OBJECT_DEFINITION))
|
13
|
+
@context.build_everything
|
14
|
+
end
|
15
|
+
@context
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|