ruby-adept 0.0.1
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.
- data/.gitignore +17 -0
- data/.travis.yml +6 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +16 -0
- data/adept.gemspec +33 -0
- data/autotest/discover.rb +2 -0
- data/bin/bprog +110 -0
- data/firmware/.gitignore +73 -0
- data/firmware/epp_stream/Basys2_100_250General.ucf +21 -0
- data/firmware/epp_stream/epp_controller.vhd +210 -0
- data/firmware/epp_stream/epp_stream.xise +355 -0
- data/firmware/epp_stream/fifo.vhd +178 -0
- data/firmware/epp_stream/tests/fifo_testbench.vhdl +164 -0
- data/lib/adept/boards/basys2.rb +84 -0
- data/lib/adept/boards.rb +2 -0
- data/lib/adept/connection_provider.rb +30 -0
- data/lib/adept/data_formats/bitstream.rb +116 -0
- data/lib/adept/data_formats/data_factories.rb +33 -0
- data/lib/adept/data_formats.rb +2 -0
- data/lib/adept/device.rb +127 -0
- data/lib/adept/error.rb +4 -0
- data/lib/adept/jtag/connection.rb +404 -0
- data/lib/adept/jtag/device.rb +178 -0
- data/lib/adept/jtag/devices/fpga.rb +162 -0
- data/lib/adept/jtag/devices/null.rb +0 -0
- data/lib/adept/jtag/devices/platform_flash.rb +23 -0
- data/lib/adept/jtag/devices.rb +2 -0
- data/lib/adept/jtag/error.rb +8 -0
- data/lib/adept/jtag/tap_state.rb +67 -0
- data/lib/adept/jtag/tap_states.rb +52 -0
- data/lib/adept/jtag.rb +11 -0
- data/lib/adept/low_level/connection.rb +59 -0
- data/lib/adept/low_level/device.rb +43 -0
- data/lib/adept/low_level/device_error.rb +22 -0
- data/lib/adept/low_level/device_manager.rb +142 -0
- data/lib/adept/low_level/enhanced_parallel.rb +151 -0
- data/lib/adept/low_level/error_handler.rb +60 -0
- data/lib/adept/low_level/jtag.rb +379 -0
- data/lib/adept/low_level/library.rb +173 -0
- data/lib/adept/low_level.rb +4 -0
- data/lib/adept/version.rb +3 -0
- data/lib/adept.rb +11 -0
- data/spec/firmware/epp_loopback.bit +0 -0
- data/spec/lib/adept/data_formats/bitstream_spec.rb +95 -0
- data/spec/lib/adept/data_formats/data_factories_spec.rb +42 -0
- data/spec/lib/adept/device_spec.rb +88 -0
- data/spec/lib/adept/jtag/connection_spec.rb +433 -0
- data/spec/lib/adept/jtag/device_spec.rb +107 -0
- data/spec/lib/adept/jtag/devices/fpga_spec.rb +71 -0
- data/spec/lib/adept/low_level/enhanced_parallel_spec.rb +72 -0
- data/spec/lib/adept/low_level/jtag_spec.rb +204 -0
- data/spec/spec_helpers.rb +25 -0
- metadata +240 -0
@@ -0,0 +1,164 @@
|
|
1
|
+
----------------------------------------------------------------------------------
|
2
|
+
-- Simple Synchronous FIFO
|
3
|
+
--
|
4
|
+
-- Author: Kyle J. Temkin, <ktemkin@binghamton.edu>
|
5
|
+
-- Copyright (c) Kyle J. Temkin, 2013 Binghamton University
|
6
|
+
--
|
7
|
+
-- This program is free software: you can redistribute it and/or modify
|
8
|
+
-- it under the terms of the GNU General Public License as published by
|
9
|
+
-- the Free Software Foundation, either version 3 of the License, or
|
10
|
+
-- (at your option) any later version.
|
11
|
+
--
|
12
|
+
-- This program is distributed in the hope that it will be useful,
|
13
|
+
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
-- GNU General Public License for more details.
|
16
|
+
--
|
17
|
+
-- You should have received a copy of the GNU General Public License
|
18
|
+
-- along with this program. If not, see <http://www.gnu.org/licenses/>.-
|
19
|
+
--
|
20
|
+
----------------------------------------------------------------------------------
|
21
|
+
|
22
|
+
library ieee;
|
23
|
+
use ieee.std_logic_1164.all;
|
24
|
+
use ieee.numeric_std.all;
|
25
|
+
|
26
|
+
entity fifo_testbench is
|
27
|
+
end fifo_testbench;
|
28
|
+
|
29
|
+
architecture behavior of fifo_testbench is
|
30
|
+
|
31
|
+
-- component declaration for the unit under test (uut)
|
32
|
+
|
33
|
+
component fifo
|
34
|
+
generic(
|
35
|
+
count_bits : integer;
|
36
|
+
element_width : integer
|
37
|
+
);
|
38
|
+
port(
|
39
|
+
clk : in std_logic;
|
40
|
+
reset : in std_logic;
|
41
|
+
data_in : in std_logic_vector(7 downto 0);
|
42
|
+
data_out : out std_logic_vector(7 downto 0);
|
43
|
+
count : out std_logic_vector(4 downto 0);
|
44
|
+
enqueue : in std_logic;
|
45
|
+
dequeue : in std_logic;
|
46
|
+
empty : out std_logic;
|
47
|
+
full : out std_logic
|
48
|
+
);
|
49
|
+
end component;
|
50
|
+
|
51
|
+
--
|
52
|
+
-- Convenience function which waits until juster the rising edge.
|
53
|
+
--
|
54
|
+
procedure wait_until_after_rising_edge(signal clk : in std_logic) is
|
55
|
+
begin
|
56
|
+
wait until rising_edge(clk);
|
57
|
+
wait for 1 ps;
|
58
|
+
end procedure wait_until_after_rising_edge;
|
59
|
+
|
60
|
+
--inputs
|
61
|
+
signal clk : std_logic := '0';
|
62
|
+
signal reset : std_logic := '1';
|
63
|
+
signal data_in : std_logic_vector(7 downto 0) := (others => '0');
|
64
|
+
signal enqueue : std_logic := '0';
|
65
|
+
signal dequeue : std_logic := '0';
|
66
|
+
|
67
|
+
--outputs
|
68
|
+
signal data_out : std_logic_vector(7 downto 0);
|
69
|
+
signal count : std_logic_vector(4 downto 0);
|
70
|
+
signal empty : std_logic;
|
71
|
+
signal full : std_logic;
|
72
|
+
|
73
|
+
-- clock period definitions
|
74
|
+
constant clk_period : time := 10 ns;
|
75
|
+
|
76
|
+
constant delta_delay : time := 1 ps;
|
77
|
+
|
78
|
+
begin
|
79
|
+
|
80
|
+
-- instantiate the unit under test (uut)
|
81
|
+
uut: fifo
|
82
|
+
generic map(
|
83
|
+
count_bits => 5,
|
84
|
+
element_width => 8
|
85
|
+
)
|
86
|
+
port map (
|
87
|
+
clk => clk,
|
88
|
+
reset => reset,
|
89
|
+
data_in => data_in,
|
90
|
+
data_out => data_out,
|
91
|
+
count => count,
|
92
|
+
enqueue => enqueue,
|
93
|
+
dequeue => dequeue,
|
94
|
+
empty => empty,
|
95
|
+
full => full
|
96
|
+
);
|
97
|
+
|
98
|
+
--Generate the system clock.
|
99
|
+
clk <= not clk after clk_period / 2;
|
100
|
+
|
101
|
+
-- stimulus process
|
102
|
+
stim_proc: process
|
103
|
+
begin
|
104
|
+
|
105
|
+
-- assert reset for 100ns;
|
106
|
+
wait for 100 ns;
|
107
|
+
reset <= '0';
|
108
|
+
|
109
|
+
--Assert conditions after reset.
|
110
|
+
assert data_out = x"00" report "Data_out should be zero after clear.";
|
111
|
+
assert count = "00000" report "Count should be zero after clear.";
|
112
|
+
assert empty = '1' report "Empty should be one after clear.";
|
113
|
+
|
114
|
+
--Add 31 elements to the FIFO.
|
115
|
+
enqueue <= '1';
|
116
|
+
dequeue <= '0';
|
117
|
+
for i in 1 to 31 loop
|
118
|
+
|
119
|
+
--Ensure that we're counting the values properly.
|
120
|
+
assert count = std_logic_vector(to_unsigned(i - 1, 5)) report "Count should be equal to the amount of elements enqueued.";
|
121
|
+
|
122
|
+
--Set up the FIFO to add a new, numbered element.
|
123
|
+
data_in <= std_logic_vector(to_unsigned(i, 8));
|
124
|
+
|
125
|
+
--Wait until just after the next rising-edge of the clock.
|
126
|
+
wait_until_after_rising_edge(clk);
|
127
|
+
|
128
|
+
--Check to see that our enqueue is behaving properly.
|
129
|
+
assert empty = '0' report "Empty should not be one while there are elements in the FIFO.";
|
130
|
+
assert data_out = x"01" report "Data out should show the first element enqueued until a dequeue is performed.";
|
131
|
+
|
132
|
+
end loop;
|
133
|
+
|
134
|
+
--Check to see that the FIFO is full.
|
135
|
+
assert full = '1' report "After adding 31 elements to the FIFO, it should be full.";
|
136
|
+
|
137
|
+
--Verify that we can perform simultaneous read/writes, even when the FIFO is full.
|
138
|
+
enqueue <= '1';
|
139
|
+
dequeue <= '1';
|
140
|
+
data_in <= x"20";
|
141
|
+
wait_until_after_rising_edge(clk);
|
142
|
+
|
143
|
+
--Check to ensure that the simultaneous enqueue/dequeue does not affect the count.
|
144
|
+
assert data_out = x"02" report "After a dequeue, the next value in the FIFO should be exposed.";
|
145
|
+
assert count = "11111" report "A simultaneous enqueue/dequeue should not affect the count.";
|
146
|
+
|
147
|
+
--Remove each of the elements from the FIFO.
|
148
|
+
enqueue <= '0';
|
149
|
+
dequeue <= '1';
|
150
|
+
for i in 2 to 32 loop
|
151
|
+
assert data_out = std_logic_vector(to_unsigned(i, 8)) report "Elements should be dequeued in the same ordered they were entered.";
|
152
|
+
assert count = std_logic_vector(to_unsigned(33 - i, 5)) report "Count should decrease as elements are dequeued.";
|
153
|
+
wait_until_after_rising_edge(clk);
|
154
|
+
end loop;
|
155
|
+
|
156
|
+
--Check to ensure that the FIFO is empty after all elements have been dequeued.
|
157
|
+
assert count = "00000" report "After all elements are dequeued, the count should be zero.";
|
158
|
+
assert empty = '1' report "After all elements are dequeued, the queue should be empty.";
|
159
|
+
|
160
|
+
report "Test complete.";
|
161
|
+
wait;
|
162
|
+
end process;
|
163
|
+
|
164
|
+
end;
|
@@ -0,0 +1,84 @@
|
|
1
|
+
|
2
|
+
require 'adept'
|
3
|
+
|
4
|
+
module Adept
|
5
|
+
module Boards
|
6
|
+
|
7
|
+
#
|
8
|
+
# Basys2 System Board
|
9
|
+
#
|
10
|
+
class Basys2 < Adept::Device
|
11
|
+
|
12
|
+
DEVICE_NAME = 'Basys2'
|
13
|
+
|
14
|
+
#
|
15
|
+
# Creates a new Basys2 board instance given the device's path.
|
16
|
+
# If no path is provided, the first connected Basys 2 board is used.
|
17
|
+
#
|
18
|
+
def initialize(path=nil)
|
19
|
+
|
20
|
+
#If no path was provided, use the path to the first device found.
|
21
|
+
path ||= Device.path_to(DEVICE_NAME)
|
22
|
+
|
23
|
+
#Delegate the connection tasks to the base class.
|
24
|
+
super(path)
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Creates a new Basys2 board instance, using the same syntax as new,
|
30
|
+
# but accepts an optional block. If a block is given, the device will
|
31
|
+
# be automatically closed after the block is complete.
|
32
|
+
#
|
33
|
+
# Yields and returns the newly-created device.
|
34
|
+
#
|
35
|
+
def self.open(path=nil)
|
36
|
+
|
37
|
+
#Create a new Basys2 device.
|
38
|
+
device = new(path)
|
39
|
+
|
40
|
+
#If we were provided with a block, yield the device to it,
|
41
|
+
#and then close the device afterwards
|
42
|
+
if block_given?
|
43
|
+
begin
|
44
|
+
yield device
|
45
|
+
ensure
|
46
|
+
device.close
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
#Return the newly created device.
|
51
|
+
device
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Configures the Basys2 board's on-board FPGA.
|
57
|
+
# Requires use of the board's JTAG port, and thus cannot be used when its JTAG
|
58
|
+
# port is open. (The JTAG device API provides an alternative method for device
|
59
|
+
# configuration.)
|
60
|
+
#
|
61
|
+
# bitstream: The bitstream to be programmed, as a Bitstream object or byte-string
|
62
|
+
# (without headers).
|
63
|
+
#
|
64
|
+
def configure_fpga(bitstream)
|
65
|
+
|
66
|
+
begin
|
67
|
+
|
68
|
+
#Create a new JTAG connection to the board's FPGA.
|
69
|
+
jtag = JTAG::Connection.new(self)
|
70
|
+
fpga = jtag.connected_devices.first
|
71
|
+
|
72
|
+
#Configure the FPGA.
|
73
|
+
fpga.configure(bitstream)
|
74
|
+
|
75
|
+
ensure
|
76
|
+
jtag.close
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
data/lib/adept/boards.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module Adept
|
3
|
+
|
4
|
+
#
|
5
|
+
# Base for Adept connections.
|
6
|
+
#
|
7
|
+
module ConnectionProvider
|
8
|
+
|
9
|
+
# An internal list of connection types which are provided by this library.
|
10
|
+
# Each time a new Conneciton type is loaded, it is added to this array.
|
11
|
+
@supported_connections = []
|
12
|
+
|
13
|
+
#
|
14
|
+
# Triggered each time a target class extends this basic connection.
|
15
|
+
# Stores a list of all classes that extend ConnectionBase.
|
16
|
+
#
|
17
|
+
def self.extended(connection)
|
18
|
+
@supported_connections << connection
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Returns the list of all supported connection providers.
|
23
|
+
#
|
24
|
+
def self.providers
|
25
|
+
@supported_connections
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
|
2
|
+
require 'date'
|
3
|
+
require 'bindata'
|
4
|
+
|
5
|
+
require 'adept/data_formats/data_factories'
|
6
|
+
|
7
|
+
module Adept
|
8
|
+
module DataFormats
|
9
|
+
|
10
|
+
#
|
11
|
+
# Class for the Xilinx bitstream file format.
|
12
|
+
#
|
13
|
+
# Format used was described at
|
14
|
+
# <http://www.fpga-faq.com/FAQ_Pages/0026_Tell_me_about_bit_files.htm>
|
15
|
+
#
|
16
|
+
class Bitstream < BinData::Record
|
17
|
+
extend DataFactories
|
18
|
+
|
19
|
+
#Data is stored in the bitstream in big endian format.
|
20
|
+
endian :big
|
21
|
+
|
22
|
+
#Bit-file header.
|
23
|
+
uint16 :header_length
|
24
|
+
string :header, :read_length => :header_length
|
25
|
+
skip :length => 2
|
26
|
+
|
27
|
+
#Design information.
|
28
|
+
uint8 :a, :check_value => 'a'.ord
|
29
|
+
uint16 :info_length
|
30
|
+
string :info, :read_length => :info_length, :trim_padding => true
|
31
|
+
|
32
|
+
#Part information
|
33
|
+
uint8 :b, :check_value => 'b'.ord
|
34
|
+
uint16 :part_length
|
35
|
+
string :part, :read_length => :part_length, :trim_padding => true
|
36
|
+
|
37
|
+
#Date of creation.
|
38
|
+
uint8 :c, :check_value => 'c'.ord
|
39
|
+
uint16 :date_length
|
40
|
+
string :raw_date, :read_length => :date_length, :trim_padding => true
|
41
|
+
|
42
|
+
#Time of creation.
|
43
|
+
uint8 :d, :check_value => 'd'.ord
|
44
|
+
uint16 :time_length
|
45
|
+
string :raw_time, :read_length => :time_length, :trim_padding => true
|
46
|
+
|
47
|
+
#Raw binary configuration information
|
48
|
+
uint8 :e, :check_value => 'e'.ord
|
49
|
+
uint32 :bitstream_length
|
50
|
+
array :raw_bitstream, :type => :uint8, :initial_length => :bitstream_length
|
51
|
+
|
52
|
+
UsercodeFormat= /UserID=0x([0-9A-Fa-f]+)/
|
53
|
+
|
54
|
+
#
|
55
|
+
# Parses the given string as a Xilinx BitStream file.
|
56
|
+
#
|
57
|
+
def self.from_string(string)
|
58
|
+
read(string)
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Returns the routed logic ("ncd") filename from which this bitstream was created.
|
63
|
+
#
|
64
|
+
def filename
|
65
|
+
info.split(';').first
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Returns the usercode for the given design.
|
70
|
+
#
|
71
|
+
def usercode
|
72
|
+
UsercodeFormat.match(info)[1]
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Returns the time at which the bitfile was created.
|
77
|
+
#
|
78
|
+
def time_created
|
79
|
+
DateTime.parse("#{raw_date} #{raw_time}")
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Returns the length of the bitsream, in bits.
|
84
|
+
#
|
85
|
+
def bit_length
|
86
|
+
bitstream_length * 8
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# Returns the bitstream as an arran array.
|
91
|
+
#
|
92
|
+
def to_a
|
93
|
+
raw_bitstream.to_a.map { |b| self.class.reverse_byte(b) }
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Returns the bitstream as a bit string.
|
98
|
+
#
|
99
|
+
def to_s
|
100
|
+
to_a.pack("C*")
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
#
|
106
|
+
# Reverses the bit order of a given byte, using a fast algorithm from the
|
107
|
+
# following page: http://graphics.stanford.edu/~seander/bithacks.html
|
108
|
+
#
|
109
|
+
def self.reverse_byte(byte)
|
110
|
+
(((byte * 0x0802 & 0x22110) | (byte * 0x8020 & 0x88440)) * 0x10101 >> 16) % 0x100;
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
module Adept
|
3
|
+
module DataFormats
|
4
|
+
|
5
|
+
#
|
6
|
+
# Mixin which supports creating instances of data-storage containers
|
7
|
+
# from files. Classes which extend this mix-in should have a "from_string"
|
8
|
+
# class method.
|
9
|
+
#
|
10
|
+
module DataFactories
|
11
|
+
|
12
|
+
#
|
13
|
+
# Creates a new instance of the target class from a file or filename.
|
14
|
+
#
|
15
|
+
def from_file(file)
|
16
|
+
|
17
|
+
#If we have a file object, read it into memory.
|
18
|
+
if file.respond_to?(:read)
|
19
|
+
file = file.read
|
20
|
+
#Otherwise, assume we have a filename.
|
21
|
+
else
|
22
|
+
file = File::read(file)
|
23
|
+
end
|
24
|
+
|
25
|
+
#Create a new instance of the extending class from the given file.
|
26
|
+
from_string(file)
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
data/lib/adept/device.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
|
2
|
+
require 'adept/low_level'
|
3
|
+
|
4
|
+
require 'adept/connection_provider'
|
5
|
+
require 'adept/jtag'
|
6
|
+
|
7
|
+
module Adept
|
8
|
+
|
9
|
+
#
|
10
|
+
# Basic interface to a Digilent Adept device.
|
11
|
+
#
|
12
|
+
class Device
|
13
|
+
|
14
|
+
#Get an easy reference to the adept Device Manager API.
|
15
|
+
DeviceManager = LowLevel::DeviceManager
|
16
|
+
|
17
|
+
#Allow Device connections to be created with an open function,
|
18
|
+
#like Ruby I/O objects.
|
19
|
+
class << self
|
20
|
+
alias :open :new
|
21
|
+
end
|
22
|
+
|
23
|
+
#Allow access to the device's handle, for now.
|
24
|
+
attr_reader :handle
|
25
|
+
|
26
|
+
#
|
27
|
+
# Factory method which returns a connection to the device with the given name,
|
28
|
+
# or nil if no devices with that name could be found.
|
29
|
+
#
|
30
|
+
def self.by_name(name)
|
31
|
+
|
32
|
+
#Find path to the first device with the given name.
|
33
|
+
path = path_to(name)
|
34
|
+
|
35
|
+
#Return a new connection to the target device, or nil if no path was found.
|
36
|
+
path ? self.new(path) : nil
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Returns the path to first device with the given name,
|
42
|
+
# or nil if no devices with that name could be found.
|
43
|
+
#
|
44
|
+
def self.path_to(name)
|
45
|
+
|
46
|
+
#Find the first device with the given name.
|
47
|
+
target_device = connected_devices.find { |device| device[:name] == name }
|
48
|
+
|
49
|
+
#Return the path to the target device.
|
50
|
+
target_device ? target_device[:path] : nil
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
#
|
56
|
+
#Creates a new connection to a Digilent adept device.
|
57
|
+
#
|
58
|
+
def initialize(path)
|
59
|
+
|
60
|
+
#Open the device, and store its handle.
|
61
|
+
@handle = DeviceManager::open_device(path)
|
62
|
+
|
63
|
+
#If we didn't get a valid handle, raise the relevant exception.
|
64
|
+
if @handle.nil?
|
65
|
+
raise DeviceManager::last_error
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
#
|
72
|
+
# Closes the given device.
|
73
|
+
#
|
74
|
+
def close
|
75
|
+
ensure_handle_is_valid
|
76
|
+
DeviceManager::close_device(@handle)
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# TODO: throw an exception of our handle is nil
|
81
|
+
#
|
82
|
+
def ensure_handle_is_valid
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Returns a list of connection methods supported by the current device.
|
88
|
+
#
|
89
|
+
def supported_connections
|
90
|
+
ConnectionProvider.providers.select { |connection| connection.supported_by?(@handle) }
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# Returns an array of information regarding connected devices.
|
95
|
+
# Each array member is a hash, with three members:
|
96
|
+
# -:name, the device's shortname
|
97
|
+
# -:connection, the device's connection
|
98
|
+
# -:transport, a code indicating the method by which we're connecting to the device
|
99
|
+
#
|
100
|
+
def self.connected_devices
|
101
|
+
|
102
|
+
#Populate the internal device list, retrieving the amount of connected devices.
|
103
|
+
count = DeviceManager::populate_device_list
|
104
|
+
|
105
|
+
#Get the device information for each of the given devices.
|
106
|
+
devices = (0...count).map { |index| DeviceManager::get_device_info(index) }
|
107
|
+
|
108
|
+
#Free the internal device list.
|
109
|
+
DeviceManager::free_device_list
|
110
|
+
|
111
|
+
#and return the list of connected devices
|
112
|
+
devices
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Returns a new connection to the first connected device.
|
118
|
+
#
|
119
|
+
def self.open_first_connected_device
|
120
|
+
device = connected_devices.first
|
121
|
+
new(device[:path])
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
data/lib/adept/error.rb
ADDED