ffi-k8055 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+
2
+ 2011-06-06 Jérémy Zurcher <jeremy@asynk.ch>
3
+ * Project creation
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2011 Jérémy Zurcher
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
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell 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
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,69 @@
1
+ ffi-k8055
2
+ by Jérémy Zurcher
3
+ http://asynk.ch
4
+
5
+ == DESCRIPTION:
6
+
7
+ A ruby-ffi binding to libk8055, an open source library to access Velleman's k8055 USB board.
8
+ This is part of k8055[https://github.com/jeremyz/k8055]
9
+
10
+ == FEATURES/PROBLEMS:
11
+
12
+ # TODO
13
+
14
+ == SYNOPSIS:
15
+
16
+ require 'k8055'
17
+ puts "K8055 version : #{K8055.version}"
18
+ @k = K8055::K8055.new
19
+ @k.open_device 0
20
+ @k.write_analog_channel 1, 128
21
+ @k.k8055_set_analog_channel 2
22
+ @k.close_device
23
+
24
+ For more examples you may look at:
25
+
26
+ * the spec/[https://github.com/jeremyz/k8055/tree/master/ruby/ffi-k8055/spec] folder
27
+
28
+ == REQUIREMENTS:
29
+
30
+ * You need to first install libk8055[https://github.com/jeremyz/k8055]
31
+
32
+ == DOWNLOAD/INSTALL:
33
+
34
+ From rubygems:
35
+
36
+ [sudo] gem install ffi-k8055
37
+
38
+ or from the git repository on github:
39
+
40
+ git clone git://github.com/jeremyz/k8055.git
41
+ cd k8055/ruby/ffi-k8055
42
+ rake gem:install
43
+
44
+ == RESOURCES:
45
+
46
+ You can find this project in a few places:
47
+
48
+ Online repositories:
49
+
50
+ * https://github.com/jeremyz/k8055
51
+ * http://cgit.asynk.ch/cgi-bin/cgit/k8055
52
+ * https://gitorious.org/k8055
53
+
54
+ Gem:
55
+
56
+ * https://rubygems.org/gems/ffi-k8055
57
+
58
+ == CREDITS:
59
+
60
+ Special thanks to:
61
+
62
+ * Sven Lindberg
63
+ * Pjetur G. Hjaltason
64
+ * Martin Pischky
65
+ * Etienne Mouragnon
66
+
67
+ == LICENSE:
68
+
69
+ See MIT-LICENSE file.
@@ -0,0 +1,62 @@
1
+ # -*- coding: UTF-8 -*-
2
+ #
3
+ load './tasks/setup.rb'
4
+ #
5
+ # Project general information
6
+ PROJ.name = 'ffi-k8055'
7
+ PROJ.authors = 'Jérémy Zurcher'
8
+ PROJ.email = 'jeremy@asynk.ch'
9
+ PROJ.url = 'https://github.com/jeremyz/k8055'
10
+ major = minor = patch = nil
11
+ File.open('../../CMakeLists.txt').each do |l|
12
+ major = $1 if l=~/VERSION_MAJOR\s+\"(\d+)\"/
13
+ minor = $1 if l=~/VERSION_MINOR\s+\"(\d+)\"/
14
+ patch = $1 if l=~/VERSION_PATCH\s+\"(\d+)\"/
15
+ end
16
+ PROJ.version = "#{major}.#{minor}.#{patch}"
17
+ PROJ.rubyforge.name = 'none'
18
+ PROJ.readme_file = 'README.rdoc'
19
+ #
20
+ # Annoucement
21
+ PROJ.ann.paragraphs << 'FEATURES' << 'SYNOPSIS' << 'REQUIREMENTS' << 'DOWNLOAD/INSTALL' << 'CREDITS' << 'LICENSE'
22
+ PROJ.ann.email[:from] = 'jeremy@asynk.ch'
23
+ PROJ.ann.email[:to] = ['FIXME']
24
+ PROJ.ann.email[:server] = 'localhost'
25
+ PROJ.ann.email[:tls] = false
26
+ # Gem specifications
27
+ PROJ.gem.need_tar = false
28
+ PROJ.gem.files = %w(Changelog MIT-LICENSE README.rdoc Rakefile) + Dir.glob("{ext,lib,spec,tasks}/**/*[^~]").reject { |fn| test ?d, fn }
29
+ PROJ.gem.platform = Gem::Platform::RUBY
30
+ PROJ.gem.required_ruby_version = ">= 1.9.2"
31
+ #
32
+ # Override Mr. Bones autogenerated extensions and force ours in
33
+ #PROJ.gem.extras['extensions'] = %w(ext/extconf.rb)
34
+ #PROJ.gem.extras['required_ruby_version'] = ">= 1.9.2"
35
+ #
36
+ # RDoc
37
+ PROJ.rdoc.exclude << '^ext\/'
38
+ PROJ.rdoc.opts << '-x' << 'ext'
39
+ #
40
+ # Ruby
41
+ PROJ.ruby_opts = []
42
+ PROJ.ruby_opts << '-I' << 'lib'
43
+ #
44
+ # RSpec
45
+ PROJ.spec.files.exclude /rbx/
46
+ PROJ.spec.opts << '--color'
47
+ #
48
+ # Rcov
49
+ PROJ.rcov.opts << '-I lib'
50
+ #
51
+ # Dependencies
52
+ depend_on 'ffi', '>=1.0.2'
53
+ #
54
+ task :default => [:spec]
55
+ #
56
+ desc "Build all packages"
57
+ task :package => 'gem:package'
58
+ #
59
+ desc "Install the gem locally"
60
+ task :install => 'gem:install'
61
+ #
62
+ # EOF
@@ -0,0 +1,141 @@
1
+ #! /usr/bin/env ruby
2
+ # -*- coding: UTF-8 -*-
3
+ #
4
+ require 'ffi'
5
+ #
6
+ module K8055
7
+ #
8
+ module Native
9
+ class K8055Struct < FFI::Struct
10
+ layout :dev_no, :int,
11
+ :usb_ctx, :pointer,
12
+ :usb_handle, :pointer,
13
+ :data_in, :pointer,
14
+ :data_out, :pointer,
15
+ end
16
+ #
17
+ extend FFI::Library
18
+ #
19
+ ffi_lib 'k8055'
20
+ #
21
+ typedef :pointer, :k8055_dev
22
+ #
23
+ [
24
+ [ :k8055_alloc, [], :k8055_dev],
25
+ [ :k8055_free, [:k8055_dev], :void],
26
+ [ :k8055_read, [:k8055_dev], :int],
27
+ [ :k8055_write, [:k8055_dev], :int],
28
+ [ :k8055_digital_outputs, [:k8055_dev], :int],
29
+ [ :k8055_digital_output_1, [:k8055_dev], :int],
30
+ [ :k8055_digital_output_2, [:k8055_dev], :int],
31
+ [ :k8055_digital_output_3, [:k8055_dev], :int],
32
+ [ :k8055_digital_output_4, [:k8055_dev], :int],
33
+ [ :k8055_digital_output_5, [:k8055_dev], :int],
34
+ [ :k8055_analog_output_1, [:k8055_dev], :int],
35
+ [ :k8055_analog_output_2, [:k8055_dev], :int],
36
+ [ :k8055_digital_input_1, [:k8055_dev], :int],
37
+ [ :k8055_digital_input_2, [:k8055_dev], :int],
38
+ [ :k8055_digital_input_3, [:k8055_dev], :int],
39
+ [ :k8055_digital_input_4, [:k8055_dev], :int],
40
+ [ :k8055_digital_input_5, [:k8055_dev], :int],
41
+ [ :k8055_analog_input_1, [:k8055_dev], :int],
42
+ [ :k8055_analog_input_2, [:k8055_dev], :int],
43
+ [ :k8055_counter_1, [:k8055_dev], :int],
44
+ [ :k8055_counter_2, [:k8055_dev], :int],
45
+ [ :k8055_version, [], :string],
46
+ [ :k8055_set_debug, [:int], :int],
47
+ [ :k8055_get_debug, [], :int],
48
+ [ :k8055_search_devices, [], :int],
49
+ [ :k8055_open_device, [:k8055_dev,:int], :int],
50
+ [ :k8055_close_device, [:k8055_dev], :int],
51
+ [ :k8055_set_analog_channel, [:k8055_dev,:int], :int],
52
+ [ :k8055_clear_analog_channel, [:k8055_dev,:int], :int],
53
+ [ :k8055_read_analog_channel, [:k8055_dev,:int], :int],
54
+ [ :k8055_write_analog_channel, [:k8055_dev,:int,:int], :int],
55
+ [ :k8055_set_all_analog, [:k8055_dev], :int],
56
+ [ :k8055_clear_all_analog, [:k8055_dev], :int],
57
+ [ :k8055_read_all_analog, [:k8055_dev,:pointer,:pointer], :int],
58
+ [ :k8055_write_all_analog, [:k8055_dev,:int,:int], :int],
59
+ [ :k8055_set_digital_channel, [:k8055_dev,:int], :int],
60
+ [ :k8055_clear_digital_channel, [:k8055_dev,:int], :int],
61
+ [ :k8055_read_digital_channel, [:k8055_dev,:int], :int],
62
+ [ :k8055_set_all_digital, [:k8055_dev], :int],
63
+ [ :k8055_clear_all_digital, [:k8055_dev], :int],
64
+ [ :k8055_read_all_digital, [:k8055_dev], :int],
65
+ [ :k8055_write_all_digital, [:k8055_dev,:int], :int],
66
+ [ :k8055_write_all_outputs, [:k8055_dev,:int,:int,:int], :int],
67
+ [ :k8055_read_all_inputs, [:k8055_dev,:pointer,:pointer,:pointer,:pointer,:pointer], :int],
68
+ [ :k8055_reset_counter, [:k8055_dev,:int], :int],
69
+ [ :k8055_read_counter, [:k8055_dev,:int], :int],
70
+ ].each do |func|
71
+ begin
72
+ attach_function(*func)
73
+ rescue Object => e
74
+ puts "Could not attach #{func} #{e.message}"
75
+ end
76
+ end
77
+ #
78
+ end
79
+ #
80
+ def self.version
81
+ Native.k8055_version
82
+ end
83
+ #
84
+ def self.search_devices
85
+ Native.k8055_search_devices
86
+ end
87
+ #
88
+ class K8055
89
+ def initialize n=nil
90
+ @dev = FFI::AutoPointer.new Native.k8055_alloc, K8055.method(:release)
91
+ open n unless n.nil?
92
+ end
93
+ def self.release p
94
+ Native.k8055_free p unless p.nil?
95
+ end
96
+ def free
97
+ Native.k8055_close_device @dev
98
+ @dev.autorelease=false if not @dev.nil?
99
+ K8055.release @dev
100
+ @dev=nil
101
+ end
102
+ def self.version
103
+ Native.k8055_version
104
+ end
105
+ def k8055_read_all_analog
106
+ a1 = FFI::MemoryPointer.new :int
107
+ a2 = FFI::MemoryPointer.new :int
108
+ Native.k8055_read_all_analog @dev, a1, a2
109
+ [ a1.read_int, a2.read_int ]
110
+ end
111
+ alias :read_all_analog :k8055_read_all_analog
112
+ def k8055_read_all_values
113
+ a1 = FFI::MemoryPointer.new :int
114
+ a2 = FFI::MemoryPointer.new :int
115
+ Native.k8055_read_all_analog @dev, a1, a2
116
+ [ a1.read_int, a2.read_int ]
117
+ end
118
+ alias :read_all_values :k8055_read_all_values
119
+ def method_missing m, *args, &block
120
+ m_s = m.to_s
121
+ meth = (
122
+ if Native.respond_to? m_s
123
+ m_s
124
+ elsif Native.respond_to? 'k8055_'+m_s
125
+ 'k8055_'+m_s
126
+ else
127
+ nil
128
+ end
129
+ )
130
+ if not meth.nil?
131
+ # self.class.class_eval "def #{m} *args, &block; r=Native.#{meth}(@dev,*args); yield r if block_given?; r; end"
132
+ self.class.class_eval "def #{m} *args, &block; Native.#{meth}(@dev,*args); end"
133
+ return self.send m, *args, &block
134
+ end
135
+ Kernel.raise NameError.new "#{self.class.name} is unable to resolve #{m}"
136
+ end
137
+ end
138
+ #
139
+ end
140
+ #
141
+ # EOF
@@ -0,0 +1,147 @@
1
+ #! /usr/bin/env ruby
2
+ # -*- coding: UTF-8 -*-
3
+ #
4
+ require 'k8055'
5
+ #
6
+ describe K8055 do
7
+ #
8
+ it "version should work" do
9
+ K8055::K8055.version.should == K8055.version
10
+ end
11
+ #
12
+ it "search_devices should find one" do
13
+ K8055.search_devices.should > 0
14
+ end
15
+ #
16
+ describe K8055 do
17
+ #
18
+ before(:all) {
19
+ @k = K8055::K8055.new
20
+ @k.open_device 0
21
+ }
22
+ after(:all) {
23
+ @k.close_device
24
+ @k.free
25
+ }
26
+ #
27
+ it "analog output 1" do
28
+ @k.k8055_set_analog_channel 1
29
+ @k.k8055_analog_output_1.should == 255
30
+ @k.k8055_write_analog_channel 1, 10
31
+ @k.k8055_analog_output_1.should == 10
32
+ @k.k8055_write_analog_channel 1, 250
33
+ @k.k8055_analog_output_1.should == 250
34
+ @k.k8055_clear_analog_channel 1
35
+ @k.k8055_analog_output_1.should == 0
36
+ @k.set_analog_channel 1
37
+ @k.analog_output_1.should == 255
38
+ @k.write_analog_channel 1, 10
39
+ @k.analog_output_1.should == 10
40
+ @k.write_analog_channel 1, 250
41
+ @k.analog_output_1.should == 250
42
+ @k.clear_analog_channel 1
43
+ @k.analog_output_1.should == 0
44
+ end
45
+ it "analog output 2" do
46
+ @k.k8055_set_analog_channel 2
47
+ @k.k8055_analog_output_2.should == 255
48
+ @k.k8055_write_analog_channel 2, 10
49
+ @k.k8055_analog_output_2.should == 10
50
+ @k.k8055_write_analog_channel 2, 250
51
+ @k.k8055_analog_output_2.should == 250
52
+ @k.k8055_clear_analog_channel 2
53
+ @k.k8055_analog_output_2.should == 0
54
+ @k.set_analog_channel 2
55
+ @k.analog_output_2.should == 255
56
+ @k.write_analog_channel 2, 10
57
+ @k.analog_output_2.should == 10
58
+ @k.write_analog_channel 2, 250
59
+ @k.analog_output_2.should == 250
60
+ @k.clear_analog_channel 2
61
+ @k.analog_output_2.should == 0
62
+ end
63
+ #
64
+ it "digital output 1" do
65
+ @k.set_all_digital
66
+ @k.digital_output_1.should == 1
67
+ @k.clear_digital_channel 1
68
+ @k.digital_output_1.should == 0
69
+ @k.set_digital_channel 1
70
+ @k.digital_output_1.should == 1
71
+ @k.clear_all_digital
72
+ @k.digital_output_1.should == 0
73
+ end
74
+ #
75
+ it "digital output 2" do
76
+ @k.set_all_digital
77
+ @k.digital_output_2.should == 1
78
+ @k.clear_digital_channel 2
79
+ @k.digital_output_2.should == 0
80
+ @k.set_digital_channel 2
81
+ @k.digital_output_2.should == 1
82
+ @k.clear_all_digital
83
+ @k.digital_output_2.should == 0
84
+ end
85
+ #
86
+ it "digital output 3" do
87
+ @k.set_all_digital
88
+ @k.digital_output_3.should == 1
89
+ @k.clear_digital_channel 3
90
+ @k.digital_output_3.should == 0
91
+ @k.set_digital_channel 3
92
+ @k.digital_output_3.should == 1
93
+ @k.clear_all_digital
94
+ @k.digital_output_3.should == 0
95
+ end
96
+ #
97
+ it "digital output 4" do
98
+ @k.set_all_digital
99
+ @k.digital_output_4.should == 1
100
+ @k.clear_digital_channel 4
101
+ @k.digital_output_4.should == 0
102
+ @k.set_digital_channel 4
103
+ @k.digital_output_4.should == 1
104
+ @k.clear_all_digital
105
+ @k.digital_output_4.should == 0
106
+ end
107
+ #
108
+ it "digital output 5" do
109
+ @k.set_all_digital
110
+ @k.digital_output_5.should == 1
111
+ @k.clear_digital_channel 5
112
+ @k.digital_output_5.should == 0
113
+ @k.set_digital_channel 5
114
+ @k.digital_output_5.should == 1
115
+ @k.clear_all_digital
116
+ @k.digital_output_5.should == 0
117
+ end
118
+ #
119
+ it "outputs test loop" do
120
+ @k.set_all_digital
121
+ @k.set_all_analog
122
+ @k.digital_outputs.should == 255
123
+ @k.digital_output_1.should == 1
124
+ @k.digital_output_2.should == 1
125
+ @k.digital_output_3.should == 1
126
+ @k.digital_output_4.should == 1
127
+ @k.digital_output_5.should == 1
128
+ @k.analog_output_1.should == 255
129
+ @k.analog_output_2.should == 255
130
+ (0..255).each do |n|
131
+ @k.write_all_digital n
132
+ @k.write_all_analog n, n
133
+ @k.digital_outputs.should == n
134
+ end
135
+ @k.clear_all_digital
136
+ @k.clear_all_analog
137
+ @k.digital_outputs.should == 0
138
+ @k.digital_output_1.should == 0
139
+ @k.digital_output_2.should == 0
140
+ @k.digital_output_3.should == 0
141
+ @k.digital_output_4.should == 0
142
+ @k.digital_output_5.should == 0
143
+ @k.analog_output_1.should == 0
144
+ @k.analog_output_2.should == 0
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,83 @@
1
+ # -*- coding: UTF-8 -*-
2
+ #
3
+ begin
4
+ require 'bones/smtp_tls'
5
+ rescue LoadError
6
+ require 'net/smtp'
7
+ end
8
+ require 'time'
9
+
10
+ namespace :ann do
11
+
12
+ # A prerequisites task that all other tasks depend upon
13
+ task :prereqs
14
+ file PROJ.ann.file do
15
+ ann = PROJ.ann
16
+ puts "Generating #{ann.file}"
17
+ File.open(ann.file,'w') do |fd|
18
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
19
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
20
+ fd.puts(" #{PROJ.url}") if PROJ.url.valid?
21
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
22
+ fd.puts
23
+ fd.puts("== DESCRIPTION")
24
+ fd.puts
25
+ fd.puts(PROJ.description)
26
+ fd.puts
27
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
28
+ fd.puts
29
+ ann.paragraphs.each do |p|
30
+ fd.puts "== #{p.upcase}"
31
+ fd.puts
32
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
33
+ fd.puts
34
+ end
35
+ fd.puts ann.text if ann.text
36
+ end
37
+ end
38
+
39
+ desc "Create an announcement file"
40
+ task :announcement => ['ann:prereqs', PROJ.ann.file]
41
+
42
+ desc "Send an email announcement"
43
+ task :email => ['ann:prereqs', PROJ.ann.file] do
44
+ ann = PROJ.ann
45
+ from = ann.email[:from] || Array(PROJ.authors).first || PROJ.email
46
+ to = Array(ann.email[:to])
47
+
48
+ ### build a mail header for RFC 822
49
+ rfc822msg = "From: #{from}\n"
50
+ rfc822msg << "To: #{to.join(',')}\n"
51
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
52
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
53
+ rfc822msg << "\n"
54
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
55
+ rfc822msg << "Message-Id: "
56
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
57
+ rfc822msg << File.read(ann.file)
58
+
59
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
60
+ ann.email[key]
61
+ end
62
+
63
+ params[3] = (PROJ.ann.email[:from] || PROJ.email) if params[3].nil?
64
+
65
+ # if ann.email[:tls] and params[4].nil?
66
+ if params[4].nil?
67
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
68
+ params[4] = STDIN.gets.chomp
69
+ end
70
+ # params = params.shift 2 if not ann.email[:tls]
71
+
72
+ ### send email
73
+ # TODO find a way to bypass /var/lib/gems/1.9/gems/bones-3.6.5/lib/bones/smtp_tls.rb which forces starttls usage
74
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
75
+ end
76
+ end # namespace :ann
77
+
78
+ desc 'Alias to ann:announcement'
79
+ task :ann => 'ann:announcement'
80
+
81
+ CLOBBER << PROJ.ann.file
82
+
83
+ # EOF