ffi-k8055 0.5.0

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.
@@ -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