libftdi-ruby 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 +7 -0
- data/.yardopts +10 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/README.md +2 -0
- data/Rakefile +6 -0
- data/lib/ftdi.rb +203 -0
- data/lib/ftdi/version.rb +6 -0
- data/libftdi-ruby.gemspec +24 -0
- data/test.rb +54 -0
- metadata +78 -0
data/.gitignore
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2010-2011 Akzhan Abdulin and contributors
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.md
ADDED
data/Rakefile
ADDED
data/lib/ftdi.rb
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require "ftdi/version"
|
3
|
+
|
4
|
+
module Ftdi
|
5
|
+
extend FFI::Library
|
6
|
+
|
7
|
+
ffi_lib "libftdi"
|
8
|
+
|
9
|
+
# FTDI chip type.
|
10
|
+
ChipType = enum(:type_am, :type_bm, :type_2232c, :type_r, :type_2232h, :type_4232h, :type_232h)
|
11
|
+
|
12
|
+
# Automatic loading / unloading of kernel modules
|
13
|
+
ModuleDetachMode = enum(:auto_detach_sio_module, :dont_detach_sio_module)
|
14
|
+
|
15
|
+
# Number of bits for {Ftdi::Context.set_line_property}
|
16
|
+
BitsType = enum(
|
17
|
+
:bits_7, 7,
|
18
|
+
:bits_8, 8
|
19
|
+
)
|
20
|
+
|
21
|
+
# Number of stop bits for {Ftdi::Context.set_line_property}
|
22
|
+
StopbitsType = enum(
|
23
|
+
:stop_bit_1, 0,
|
24
|
+
:stop_bit_15, 1,
|
25
|
+
:stop_bit_2, 2
|
26
|
+
)
|
27
|
+
|
28
|
+
# Parity mode for {Ftdi::Context.set_line_property}
|
29
|
+
ParityType = enum(:none, :odd, :even, :mark, :space)
|
30
|
+
|
31
|
+
# Break type for {Ftdi::Context.set_line_property2}
|
32
|
+
BreakType = enum(:break_off, :break_on)
|
33
|
+
|
34
|
+
SIO_DISABLE_FLOW_CTRL = 0x0
|
35
|
+
|
36
|
+
# Base error of libftdi.
|
37
|
+
class Error < RuntimeError; end
|
38
|
+
|
39
|
+
# Initialization error of libftdi.
|
40
|
+
class CannotInitializeContextError < Error; end
|
41
|
+
|
42
|
+
# Error of libftdi with its status code.
|
43
|
+
class StatusCodeError < Error
|
44
|
+
attr_accessor :status_code
|
45
|
+
|
46
|
+
def initialize(status_code, message)
|
47
|
+
super(message)
|
48
|
+
self.status_code = status_code
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
"#{status_code}: #{super}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# libftdi context
|
57
|
+
class Context < FFI::Struct
|
58
|
+
layout(
|
59
|
+
# USB specific
|
60
|
+
# libusb's context
|
61
|
+
:usb_ctx, :pointer,
|
62
|
+
# libusb's usb_dev_handle
|
63
|
+
:usb_dev, :pointer,
|
64
|
+
# usb read timeout
|
65
|
+
:usb_read_timeout, :int,
|
66
|
+
# usb write timeout
|
67
|
+
:usb_write_timeout, :int,
|
68
|
+
|
69
|
+
# FTDI specific
|
70
|
+
# FTDI chip type
|
71
|
+
:type, Ftdi::ChipType,
|
72
|
+
# baudrate
|
73
|
+
:baudrate, :int,
|
74
|
+
# bitbang mode state
|
75
|
+
:bitbang_enabled, :uint8,
|
76
|
+
# pointer to read buffer for ftdi_read_data
|
77
|
+
:readbuffer, :pointer,
|
78
|
+
# read buffer offset
|
79
|
+
:readbuffer_offset, :uint,
|
80
|
+
# number of remaining data in internal read buffer
|
81
|
+
:readbuffer_remaining, :uint,
|
82
|
+
# read buffer chunk size
|
83
|
+
:readbuffer_chunksize, :uint,
|
84
|
+
# write buffer chunk size
|
85
|
+
:writebuffer_chunksize, :uint,
|
86
|
+
# maximum packet size. Needed for filtering modem status bytes every n packets.
|
87
|
+
:max_packet_size, :uint,
|
88
|
+
|
89
|
+
# FTDI FT2232C requirements
|
90
|
+
# FT2232C interface number: 0 or 1
|
91
|
+
:interface, :int, # 0 or 1
|
92
|
+
# FT2232C index number: 1 or 2
|
93
|
+
:index, :int, # 1 or 2
|
94
|
+
# Endpoints
|
95
|
+
# FT2232C end points: 1 or 2
|
96
|
+
:in_ep, :int,
|
97
|
+
:out_ep, :int, # 1 or 2
|
98
|
+
|
99
|
+
# Bitbang mode. 1: (default) Normal bitbang mode, 2: FT2232C SPI bitbang mode
|
100
|
+
:bitbang_mode, :uint8,
|
101
|
+
|
102
|
+
# Decoded eeprom structure
|
103
|
+
:eeprom, :pointer,
|
104
|
+
|
105
|
+
# String representation of last error
|
106
|
+
:error_str, :string,
|
107
|
+
|
108
|
+
# Defines behavior in case a kernel module is already attached to the device
|
109
|
+
:module_detach_mode, Ftdi::ModuleDetachMode
|
110
|
+
)
|
111
|
+
|
112
|
+
def initialize
|
113
|
+
ptr = Ftdi.ftdi_new
|
114
|
+
raise CannotInitializeContextError.new if ptr.nil?
|
115
|
+
super(ptr)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Deinitialize and free an ftdi context.
|
119
|
+
def dispose
|
120
|
+
Ftdi.ftdi_free(ctx)
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
|
124
|
+
alias :close :dispose
|
125
|
+
|
126
|
+
def error_string
|
127
|
+
self[:error_str]
|
128
|
+
end
|
129
|
+
|
130
|
+
# Opens the first device with a given vendor and product ids.
|
131
|
+
def usb_open(vendor, product)
|
132
|
+
raise ArgumentError.new('vendor should be Fixnum') unless vendor.kind_of?(Fixnum)
|
133
|
+
raise ArgumentError.new('product should be Fixnum') unless product.kind_of?(Fixnum)
|
134
|
+
check_result(Ftdi.ftdi_usb_open(ctx, vendor, product))
|
135
|
+
end
|
136
|
+
|
137
|
+
# Closes the ftdi device.
|
138
|
+
def usb_close
|
139
|
+
Ftdi.ftdi_usb_close(ctx)
|
140
|
+
nil
|
141
|
+
end
|
142
|
+
|
143
|
+
# Gets the chip baud rate.
|
144
|
+
def baudrate
|
145
|
+
self[:baudrate]
|
146
|
+
end
|
147
|
+
|
148
|
+
# Sets the chip baud rate.
|
149
|
+
def baudrate=(new_baudrate)
|
150
|
+
raise ArgumentError.new('baudrate should be Fixnum') unless new_baudrate.kind_of?(Fixnum)
|
151
|
+
check_result(Ftdi.ftdi_set_baudrate(ctx, new_baudrate))
|
152
|
+
end
|
153
|
+
|
154
|
+
# Set (RS232) line characteristics.
|
155
|
+
# The break type can only be set via {#set_line_property2} and defaults to "off".
|
156
|
+
def set_line_property(bits, stopbits, parity)
|
157
|
+
check_result(Ftdi.ftdi_set_line_property(ctx, bits, stopbits, parity))
|
158
|
+
end
|
159
|
+
|
160
|
+
# Set (RS232) line characteristics.
|
161
|
+
def set_line_property2(bits, stopbits, parity, _break)
|
162
|
+
check_result(Ftdi.ftdi_set_line_property2(ctx, bits, stopbits, parity, _break))
|
163
|
+
end
|
164
|
+
|
165
|
+
# Set flowcontrol for ftdi chip.
|
166
|
+
def flowctrl=(new_flowctrl)
|
167
|
+
check_result(Ftdi.ftdi_setflowctrl(ctx, new_flowctrl))
|
168
|
+
end
|
169
|
+
|
170
|
+
def write_data(bytes)
|
171
|
+
bytes = bytes.pack('c*') if bytes.respond_to?(:pack)
|
172
|
+
size = bytes.respond_to?(:bytesize) ? bytes.bytesize : bytes.size
|
173
|
+
mem_buf = FFI::MemoryPointer.new(:char, size)
|
174
|
+
mem_buf.put_bytes(0, bytes)
|
175
|
+
r = Ftdi.ftdi_write_data(ctx, mem_buf, size)
|
176
|
+
check_result(r)
|
177
|
+
r
|
178
|
+
end
|
179
|
+
|
180
|
+
private
|
181
|
+
def ctx
|
182
|
+
self.to_ptr
|
183
|
+
end
|
184
|
+
|
185
|
+
def check_result(status_code)
|
186
|
+
if status_code < 0
|
187
|
+
raise StatusCodeError.new(status_code, error_string)
|
188
|
+
end
|
189
|
+
nil
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
attach_function :ftdi_new, [ ], :pointer
|
194
|
+
attach_function :ftdi_free, [ :pointer ], :void
|
195
|
+
attach_function :ftdi_usb_open, [ :pointer, :int, :int ], :int
|
196
|
+
attach_function :ftdi_usb_close, [ :pointer ], :void
|
197
|
+
attach_function :ftdi_set_baudrate, [ :pointer, :int ], :int
|
198
|
+
attach_function :ftdi_set_line_property, [ :pointer, BitsType, StopbitsType, ParityType ], :int
|
199
|
+
attach_function :ftdi_set_line_property2, [ :pointer, BitsType, StopbitsType, ParityType, BreakType ], :int
|
200
|
+
attach_function :ftdi_setflowctrl, [ :pointer, :int ], :int
|
201
|
+
attach_function :ftdi_write_data, [ :pointer, :pointer, :int ], :int
|
202
|
+
end
|
203
|
+
|
data/lib/ftdi/version.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "ftdi/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "libftdi-ruby"
|
7
|
+
s.version = Ftdi::VERSION.dup
|
8
|
+
s.authors = ["Akzhan Abdulin"]
|
9
|
+
s.email = ["akzhan.abdulin@gmail.com"]
|
10
|
+
s.homepage = "http://github.com/akzhan/libftdi-ruby"
|
11
|
+
s.summary = %q{libftdi library binding}
|
12
|
+
s.description = %q{libftdi library binding to talk to FTDI chips}
|
13
|
+
|
14
|
+
s.rubyforge_project = "libftdi-ruby"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_runtime_dependency "ffi", "~> 1.0"
|
22
|
+
s.add_development_dependency "yard", "~> 0.7.5"
|
23
|
+
end
|
24
|
+
|
data/test.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.expand_path('lib', File.dirname(__FILE__)))
|
5
|
+
|
6
|
+
require 'ftdi'
|
7
|
+
|
8
|
+
DMX_BREAK = 110. / 1000 # Break 88 uS or more
|
9
|
+
DMX_MAB = 160. / 1000 # Mark After Break 8 uS or more
|
10
|
+
BAUD_RATE = 250000
|
11
|
+
|
12
|
+
ctx = Ftdi::Context.new
|
13
|
+
|
14
|
+
def dmx_break(ctx)
|
15
|
+
ctx.set_line_property2(:bits_8, :stop_bit_2, :none, :break_on)
|
16
|
+
sleep DMX_BREAK
|
17
|
+
ctx.set_line_property2(:bits_8, :stop_bit_2, :none, :break_off)
|
18
|
+
sleep DMX_MAB
|
19
|
+
end
|
20
|
+
|
21
|
+
def dmx_write(ctx, bytes)
|
22
|
+
dmx_break(ctx)
|
23
|
+
ctx.write_data(bytes)
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
ctx.usb_open(0x0403, 0x6001)
|
28
|
+
begin
|
29
|
+
ctx.baudrate = BAUD_RATE
|
30
|
+
ctx.set_line_property(:bits_8, :stop_bit_2, :none)
|
31
|
+
ctx.flowctrl = Ftdi::SIO_DISABLE_FLOW_CTRL
|
32
|
+
|
33
|
+
arr = [ 0 ]
|
34
|
+
512.times { arr << 1 }
|
35
|
+
dmx_write(ctx, arr)
|
36
|
+
|
37
|
+
sleep 1
|
38
|
+
|
39
|
+
arr = [ 0 ]
|
40
|
+
512.times { arr << 0 }
|
41
|
+
dmx_write(ctx, arr)
|
42
|
+
|
43
|
+
puts "Context is:"
|
44
|
+
ctx.members.each { |k| puts "#{k} = #{ctx[k]}" }
|
45
|
+
|
46
|
+
ensure
|
47
|
+
ctx.usb_close
|
48
|
+
end
|
49
|
+
rescue Ftdi::Error => e
|
50
|
+
$stderr.puts e.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
ctx.dispose
|
54
|
+
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: libftdi-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Akzhan Abdulin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ffi
|
16
|
+
requirement: &2153142340 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2153142340
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: yard
|
27
|
+
requirement: &2153157740 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.7.5
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2153157740
|
36
|
+
description: libftdi library binding to talk to FTDI chips
|
37
|
+
email:
|
38
|
+
- akzhan.abdulin@gmail.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- .yardopts
|
45
|
+
- Gemfile
|
46
|
+
- LICENSE
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- lib/ftdi.rb
|
50
|
+
- lib/ftdi/version.rb
|
51
|
+
- libftdi-ruby.gemspec
|
52
|
+
- test.rb
|
53
|
+
homepage: http://github.com/akzhan/libftdi-ruby
|
54
|
+
licenses: []
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project: libftdi-ruby
|
73
|
+
rubygems_version: 1.8.15
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: libftdi library binding
|
77
|
+
test_files: []
|
78
|
+
has_rdoc:
|