pi_driver 0.0.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.
- checksums.yaml +7 -0
- data/bin/pin.rb +4 -0
- data/lib/pi_driver/i2c_master.rb +106 -0
- data/lib/pi_driver/pin.rb +165 -0
- data/lib/pi_driver.rb +5 -0
- metadata +62 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bc90f84fe49ba85fc4c6e0f5b3af5e6396952733
|
4
|
+
data.tar.gz: 30d3039abade3868c00a0872176b243452e3a39b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d7c63839480a43a98c4a26e7e9aa20bd4d5e196b697f2eb6db48098997ffb21e2f8fd97db4cff0e5cbe01c140d3837fa8f170bdcd1f986eb2d16ec42d25c4725
|
7
|
+
data.tar.gz: '0635499eee9f47a2479e2759d72399231bce35417ccac7a9d673c858d0c3bb93ed3e018482ece97be0fc04290164f64a363e5b90cdeb708a86e245f22143f582'
|
data/bin/pin.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
module PiDriver
|
2
|
+
class I2CMaster
|
3
|
+
def initialize(options = {})
|
4
|
+
@frequency = 100_000
|
5
|
+
@delta_time = @frequency ** -1.0
|
6
|
+
@clock_pin = options[:clock_pin]
|
7
|
+
@data_pin = options[:data_pin]
|
8
|
+
@num_bits = 8
|
9
|
+
stop
|
10
|
+
end
|
11
|
+
|
12
|
+
def stop
|
13
|
+
release_clock_pin
|
14
|
+
release_data_pin
|
15
|
+
end
|
16
|
+
|
17
|
+
def start
|
18
|
+
drive_data_pin
|
19
|
+
drive_clock_pin
|
20
|
+
end
|
21
|
+
|
22
|
+
def write(byte)
|
23
|
+
send_data byte
|
24
|
+
byte
|
25
|
+
end
|
26
|
+
|
27
|
+
def read
|
28
|
+
release_data_pin
|
29
|
+
read_data
|
30
|
+
end
|
31
|
+
|
32
|
+
def ack
|
33
|
+
release_data_pin
|
34
|
+
release_clock_pin
|
35
|
+
success = @data_pin.clear?
|
36
|
+
drive_clock_pin
|
37
|
+
success
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# def send_address(direction = :read)
|
43
|
+
# byte = @slave_address << 1
|
44
|
+
# byte += Pin::Value::HIGH if direction == :read
|
45
|
+
# send_data byte
|
46
|
+
# end
|
47
|
+
|
48
|
+
def send_data(byte)
|
49
|
+
bits = byte_to_bits byte
|
50
|
+
bits.each do |bit|
|
51
|
+
bit == Pin::Value::HIGH ? release_data_pin : drive_data_pin
|
52
|
+
release_clock_pin
|
53
|
+
drive_clock_pin
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_data
|
58
|
+
bits = []
|
59
|
+
@num_bits.times do
|
60
|
+
release_clock_pin
|
61
|
+
bits << @data_pin.value
|
62
|
+
drive_clock_pin
|
63
|
+
end
|
64
|
+
bits_to_byte(bits)
|
65
|
+
end
|
66
|
+
|
67
|
+
def byte_to_bits(byte)
|
68
|
+
byte.to_s(2).rjust(@num_bits, '0').chars.map(&:to_i)
|
69
|
+
end
|
70
|
+
|
71
|
+
def bits_to_byte(bits)
|
72
|
+
bits.join.to_i(2)
|
73
|
+
end
|
74
|
+
|
75
|
+
def release_data_pin
|
76
|
+
@data_pin.input
|
77
|
+
observe_speed_requirement
|
78
|
+
end
|
79
|
+
|
80
|
+
def drive_data_pin
|
81
|
+
@data_pin.output Pin::Value::LOW
|
82
|
+
observe_speed_requirement
|
83
|
+
end
|
84
|
+
|
85
|
+
def release_clock_pin
|
86
|
+
@clock_pin.input
|
87
|
+
observe_clock_stretch
|
88
|
+
observe_speed_requirement
|
89
|
+
end
|
90
|
+
|
91
|
+
def drive_clock_pin
|
92
|
+
@clock_pin.output Pin::Value::LOW
|
93
|
+
observe_speed_requirement
|
94
|
+
end
|
95
|
+
|
96
|
+
def observe_clock_stretch
|
97
|
+
# 1ms timeout typical
|
98
|
+
loop { break if @clock_pin.set?}
|
99
|
+
end
|
100
|
+
|
101
|
+
def observe_speed_requirement
|
102
|
+
start = Time.now
|
103
|
+
loop { break if (Time.now - start) > @delta_time }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module PiDriver
|
2
|
+
class Pin
|
3
|
+
# delete this and below
|
4
|
+
DIR_BASE = File.expand_path '~/pi/gpio/sys/class'
|
5
|
+
# # uncomment below, delete this
|
6
|
+
# DIR_BASE = '/sys/class'
|
7
|
+
|
8
|
+
DIR_GPIO = "#{DIR_BASE}/gpio"
|
9
|
+
|
10
|
+
attr_reader :gpio_number
|
11
|
+
|
12
|
+
class Direction
|
13
|
+
INPUT = :in
|
14
|
+
OUTPUT = :out
|
15
|
+
VALID_DIRECTIONS = [INPUT, OUTPUT]
|
16
|
+
end
|
17
|
+
|
18
|
+
class Edge
|
19
|
+
RISING = :rising
|
20
|
+
FALLING = :falling
|
21
|
+
BOTH = :both
|
22
|
+
NONE = :none
|
23
|
+
VALID_EDGES = [RISING, FALLING, BOTH, NONE]
|
24
|
+
end
|
25
|
+
|
26
|
+
class Value
|
27
|
+
LOW = 0
|
28
|
+
HIGH = 1
|
29
|
+
VALID_VALUES = [LOW, HIGH]
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(gpio_number, options = {})
|
33
|
+
direction = options[:direction] || Direction::INPUT
|
34
|
+
value = options[:value] || Value::LOW
|
35
|
+
|
36
|
+
write_export gpio_number
|
37
|
+
|
38
|
+
write_direction(direction)
|
39
|
+
input? ? read_value : write_value(value)
|
40
|
+
end
|
41
|
+
|
42
|
+
def input
|
43
|
+
write_direction(Direction::INPUT) unless input?
|
44
|
+
end
|
45
|
+
|
46
|
+
def input?
|
47
|
+
@direction == Direction::INPUT
|
48
|
+
end
|
49
|
+
|
50
|
+
def output(value = Value::LOW)
|
51
|
+
write_direction(Direction::OUTPUT) unless output?
|
52
|
+
write_value(value)
|
53
|
+
end
|
54
|
+
|
55
|
+
def output?
|
56
|
+
@direction == Direction::OUTPUT
|
57
|
+
end
|
58
|
+
|
59
|
+
def clear
|
60
|
+
return unless output?
|
61
|
+
write_value(Value::LOW) unless clear?
|
62
|
+
@value
|
63
|
+
end
|
64
|
+
|
65
|
+
def clear?
|
66
|
+
value == Value::LOW
|
67
|
+
end
|
68
|
+
|
69
|
+
def set
|
70
|
+
return unless output?
|
71
|
+
write_value(Value::HIGH) unless set?
|
72
|
+
@value
|
73
|
+
end
|
74
|
+
|
75
|
+
def set?
|
76
|
+
value == Value::HIGH
|
77
|
+
end
|
78
|
+
|
79
|
+
def value
|
80
|
+
input? ? read_value : @value
|
81
|
+
end
|
82
|
+
|
83
|
+
def interrupt(edge = Edge::RISING)
|
84
|
+
check_arg(:edge, edge, Edge::VALID_EDGES)
|
85
|
+
|
86
|
+
@edge = edge
|
87
|
+
|
88
|
+
@interrupt_thread = Thread.new do
|
89
|
+
last_value = read_value
|
90
|
+
loop do
|
91
|
+
new_value = read_value
|
92
|
+
yield if block_given? && interrupted?(new_value, last_value)
|
93
|
+
last_value = new_value
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def clear_interrupt
|
99
|
+
@interrupt_thread.kill if @interrupt_thread
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def check_arg(type, arg, valid_options)
|
105
|
+
valid_options_for_message = valid_options.map { |value| ":#{value}"}.join(', ')
|
106
|
+
message = "Pin #{@gpio_number} invalid #{type}: #{arg} expected to be one of #{valid_options_for_message}"
|
107
|
+
raise ArgumentError, message unless valid_options.include?(arg)
|
108
|
+
end
|
109
|
+
|
110
|
+
def dir_pin
|
111
|
+
"#{DIR_GPIO}/gpio#{@gpio_number}"
|
112
|
+
end
|
113
|
+
|
114
|
+
def interrupted?(new_value, last_value)
|
115
|
+
rising_edge = new_value == Value::HIGH && last_value == Value::LOW
|
116
|
+
falling_edge = new_value == Value::LOW && last_value == Value::HIGH
|
117
|
+
|
118
|
+
case @edge
|
119
|
+
when :rising
|
120
|
+
rising_edge
|
121
|
+
when :falling
|
122
|
+
falling_edge
|
123
|
+
when :both
|
124
|
+
rising_edge || falling_edge
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def path_direction
|
129
|
+
"#{dir_pin}/direction"
|
130
|
+
end
|
131
|
+
|
132
|
+
def path_export
|
133
|
+
"#{DIR_GPIO}/export"
|
134
|
+
end
|
135
|
+
|
136
|
+
def path_value
|
137
|
+
"#{dir_pin}/value"
|
138
|
+
end
|
139
|
+
|
140
|
+
def read_direction
|
141
|
+
@direction = File.read(path_direction).to_sym
|
142
|
+
end
|
143
|
+
|
144
|
+
def read_value
|
145
|
+
@value = File.read(path_value).to_i
|
146
|
+
end
|
147
|
+
|
148
|
+
def write_direction(direction)
|
149
|
+
check_arg(:direction, direction, Direction::VALID_DIRECTIONS)
|
150
|
+
@direction = direction
|
151
|
+
File.write(path_direction, @direction)
|
152
|
+
end
|
153
|
+
|
154
|
+
def write_export(gpio_number)
|
155
|
+
@gpio_number = gpio_number
|
156
|
+
File.write(path_export, @gpio_number)
|
157
|
+
end
|
158
|
+
|
159
|
+
def write_value(value)
|
160
|
+
check_arg(:value, value, Value::VALID_VALUES)
|
161
|
+
@value = value
|
162
|
+
File.write(path_value, @value)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/lib/pi_driver.rb
ADDED
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pi_driver
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lucas Winningham
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-03-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mocha
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Ruby driver for Raspberry Pi
|
28
|
+
email: lucas.winningham@gmail.com
|
29
|
+
executables:
|
30
|
+
- pin.rb
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- bin/pin.rb
|
35
|
+
- lib/pi_driver.rb
|
36
|
+
- lib/pi_driver/i2c_master.rb
|
37
|
+
- lib/pi_driver/pin.rb
|
38
|
+
homepage: http://rubygems.org/gems/pi_driver
|
39
|
+
licenses:
|
40
|
+
- MIT
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 2.6.14
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: Ruby driver for Raspberry Pi
|
62
|
+
test_files: []
|