pi_driver 0.0.2 → 0.0.3

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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pi_driver.rb +3 -1
  3. data/lib/pi_driver/device.rb +6 -0
  4. data/lib/pi_driver/device/mcp23017.rb +129 -0
  5. data/lib/pi_driver/device/mcp23017/hardware_address.rb +37 -0
  6. data/lib/pi_driver/device/mcp23017/port.rb +23 -0
  7. data/lib/pi_driver/device/mcp23017/register.rb +98 -0
  8. data/lib/pi_driver/device/mcp23017/register/defval.rb +14 -0
  9. data/lib/pi_driver/device/mcp23017/register/gpinten.rb +14 -0
  10. data/lib/pi_driver/device/mcp23017/register/gpio.rb +14 -0
  11. data/lib/pi_driver/device/mcp23017/register/gppu.rb +14 -0
  12. data/lib/pi_driver/device/mcp23017/register/intcap.rb +14 -0
  13. data/lib/pi_driver/device/mcp23017/register/intcon.rb +14 -0
  14. data/lib/pi_driver/device/mcp23017/register/intf.rb +14 -0
  15. data/lib/pi_driver/device/mcp23017/register/iocon.rb +41 -0
  16. data/lib/pi_driver/device/mcp23017/register/iodir.rb +14 -0
  17. data/lib/pi_driver/device/mcp23017/register/ipol.rb +14 -0
  18. data/lib/pi_driver/device/mcp23017/register/olat.rb +14 -0
  19. data/lib/pi_driver/device/mcp23017/register/register_helper.rb +50 -0
  20. data/lib/pi_driver/i2c_master.rb +6 -15
  21. data/lib/pi_driver/pin.rb +25 -49
  22. data/lib/pi_driver/pin/board.rb +65 -0
  23. data/lib/pi_driver/pin/direction.rb +13 -0
  24. data/lib/pi_driver/pin/directory_helper.rb +32 -0
  25. data/lib/pi_driver/pin/file_helper.rb +32 -0
  26. data/lib/pi_driver/utils.rb +10 -0
  27. data/lib/pi_driver/utils/argument_helper.rb +19 -0
  28. data/lib/pi_driver/utils/byte.rb +21 -0
  29. data/lib/pi_driver/utils/edge.rb +17 -0
  30. data/lib/pi_driver/utils/interrupt.rb +60 -0
  31. data/lib/pi_driver/utils/state.rb +13 -0
  32. data/test/device/mcp23017/test_alias.rb +27 -0
  33. data/test/device/mcp23017/test_error.rb +37 -0
  34. data/test/device/mcp23017/test_hardware_address.rb +29 -0
  35. data/test/device/mcp23017/test_i2c_master.rb +10 -0
  36. data/test/device/mcp23017/test_read.rb +63 -0
  37. data/test/device/mcp23017/test_register.rb +118 -0
  38. data/test/device/mcp23017/test_write.rb +49 -0
  39. data/test/device/mcp23017_test_helper.rb +13 -0
  40. data/test/i2c_master/test_ack.rb +26 -0
  41. data/test/i2c_master/test_address.rb +15 -0
  42. data/test/i2c_master/test_alias.rb +7 -0
  43. data/test/i2c_master/test_clock_stretch.rb +26 -0
  44. data/test/i2c_master/test_read.rb +27 -0
  45. data/test/i2c_master/test_speed.rb +11 -0
  46. data/test/i2c_master/test_start.rb +11 -0
  47. data/test/i2c_master/test_stop.rb +24 -0
  48. data/test/i2c_master/test_write.rb +29 -0
  49. data/test/i2c_master_test_helper.rb +28 -0
  50. data/test/pin/test_alias.rb +23 -0
  51. data/test/pin/test_clear.rb +15 -0
  52. data/test/pin/test_clear_interrupt.rb +10 -0
  53. data/test/pin/test_error.rb +35 -0
  54. data/test/pin/test_input.rb +23 -0
  55. data/test/pin/test_interrupt.rb +51 -0
  56. data/test/pin/test_is_clear.rb +17 -0
  57. data/test/pin/test_is_input.rb +14 -0
  58. data/test/pin/test_is_output.rb +14 -0
  59. data/test/pin/test_is_set.rb +17 -0
  60. data/test/pin/test_output.rb +38 -0
  61. data/test/pin/test_set.rb +15 -0
  62. data/test/pin_test_helper.rb +45 -0
  63. data/test/test_helper.rb +14 -0
  64. data/test/utils/test_error.rb +31 -0
  65. data/test/utils/test_interrupt.rb +109 -0
  66. data/test/utils_test_helper.rb +6 -0
  67. metadata +73 -5
@@ -0,0 +1,14 @@
1
+ module PiDriver
2
+ class Device
3
+ class MCP23017
4
+ class Iodir < Register
5
+ def initialize(options)
6
+ options[:register] = :iodir
7
+ super(options)
8
+ end
9
+
10
+ mirror_bit_accessors :io
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module PiDriver
2
+ class Device
3
+ class MCP23017
4
+ class Ipol < Register
5
+ def initialize(options)
6
+ options[:register] = :ipol
7
+ super(options)
8
+ end
9
+
10
+ mirror_bit_accessors :ip
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module PiDriver
2
+ class Device
3
+ class MCP23017
4
+ class Olat < Register
5
+ def initialize(options)
6
+ options[:register] = :olat
7
+ super(options)
8
+ end
9
+
10
+ mirror_bit_accessors :ol
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,50 @@
1
+ module PiDriver
2
+ class Device
3
+ class MCP23017
4
+ class Register
5
+ class RegisterHelper
6
+ IODIR = :iodir
7
+ IPOL = :ipol
8
+ GPINTEN = :gpinten
9
+ DEFVAL = :defval
10
+ INTCON = :intcon
11
+ IOCON = :iocon
12
+ GPPU = :gppu
13
+ INTF = :intf
14
+ INTCAP = :intcap
15
+ GPIO = :gpio
16
+ OLAT = :olat
17
+
18
+ VALID_REGISTERS = [
19
+ IODIR,
20
+ IPOL,
21
+ GPINTEN,
22
+ DEFVAL,
23
+ INTCON,
24
+ IOCON,
25
+ GPPU,
26
+ INTF,
27
+ INTCAP,
28
+ GPIO,
29
+ OLAT
30
+ ]
31
+
32
+ def self.address(options)
33
+ bank = options[:bank]
34
+ port = options[:port]
35
+ register = options[:register]
36
+
37
+ port_index = Port::VALID_PORTS.index(port)
38
+ register_index = VALID_REGISTERS.index(register)
39
+
40
+ if bank == Utils::State::LOW
41
+ port_index + register_index * 0x02
42
+ else
43
+ port_index * 0x10 + register_index
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -5,7 +5,6 @@ module PiDriver
5
5
  @delta_time = @frequency ** -1.0
6
6
  @clock_pin = options[:clock_pin]
7
7
  @data_pin = options[:data_pin]
8
- @num_bits = 8
9
8
  stop
10
9
  end
11
10
 
@@ -50,9 +49,9 @@ module PiDriver
50
49
  private
51
50
 
52
51
  def send_data(byte)
53
- bits = byte_to_bits byte
52
+ bits = Utils::Byte.byte_to_bits(byte)
54
53
  bits.each do |bit|
55
- bit == Pin::Value::HIGH ? release_data_pin : drive_data_pin
54
+ bit == Utils::State::HIGH ? release_data_pin : drive_data_pin
56
55
  release_clock_pin
57
56
  drive_clock_pin
58
57
  end
@@ -60,20 +59,12 @@ module PiDriver
60
59
 
61
60
  def read_data
62
61
  bits = []
63
- @num_bits.times do
62
+ Utils::Byte::NUM_BITS_PER_BYTE.times do
64
63
  release_clock_pin
65
64
  bits << @data_pin.value
66
65
  drive_clock_pin
67
66
  end
68
- bits_to_byte(bits)
69
- end
70
-
71
- def byte_to_bits(byte)
72
- byte.to_s(2).rjust(@num_bits, '0').chars.map(&:to_i)
73
- end
74
-
75
- def bits_to_byte(bits)
76
- bits.join.to_i(2)
67
+ Utils::Byte.bits_to_byte(bits)
77
68
  end
78
69
 
79
70
  def release_data_pin
@@ -82,7 +73,7 @@ module PiDriver
82
73
  end
83
74
 
84
75
  def drive_data_pin
85
- @data_pin.output Pin::Value::LOW
76
+ @data_pin.output Utils::State::LOW
86
77
  observe_speed_requirement
87
78
  end
88
79
 
@@ -93,7 +84,7 @@ module PiDriver
93
84
  end
94
85
 
95
86
  def drive_clock_pin
96
- @clock_pin.output Pin::Value::LOW
87
+ @clock_pin.output Utils::State::LOW
97
88
  observe_speed_requirement
98
89
  end
99
90
 
data/lib/pi_driver/pin.rb CHANGED
@@ -1,30 +1,29 @@
1
- require_relative 'pin/argument_helper'
2
1
  require_relative 'pin/board'
3
2
  require_relative 'pin/direction'
4
- require_relative 'pin/edge'
5
3
  require_relative 'pin/file_helper'
6
- require_relative 'pin/value'
7
4
 
8
5
  module PiDriver
9
6
  class Pin
10
7
  attr_reader :gpio_number
11
8
 
12
9
  def initialize(gpio_number, options = {})
13
- @argument_helper = ArgumentHelper.new gpio_number
10
+ @argument_helper = Utils::ArgumentHelper.new prefix: "PiDriver::Pin"
14
11
 
15
12
  @gpio_number = gpio_number
16
13
  @argument_helper.check(:gpio_number, @gpio_number, Board::VALID_NUMBERS)
17
14
 
15
+ @argument_helper.prefix = "PiDriver::Pin ##{gpio_number}"
16
+
18
17
  @direction = options[:direction] || Direction::INPUT
19
18
  @argument_helper.check(:direction, @direction, Direction::VALID_DIRECTIONS)
20
19
 
21
- @value = options[:value] || Value::LOW
22
- @argument_helper.check(:value, @value, Value::VALID_VALUES)
20
+ @state = options[:state] || Utils::State::LOW
21
+ @argument_helper.check(:state, @state, Utils::State::VALID_STATES)
23
22
 
24
23
  @file_helper = FileHelper.new @gpio_number
25
24
  @file_helper.write_export
26
25
  @file_helper.write_direction(@direction)
27
- input? ? @file_helper.read_value : @file_helper.write_value(@value)
26
+ input? ? @file_helper.read_value : @file_helper.write_value(@state)
28
27
  end
29
28
 
30
29
  def input
@@ -36,12 +35,12 @@ module PiDriver
36
35
  @direction == Direction::INPUT
37
36
  end
38
37
 
39
- def output(value = Value::LOW)
40
- @argument_helper.check(:value, value, Value::VALID_VALUES)
41
- @value = value
38
+ def output(state = Utils::State::LOW)
39
+ @argument_helper.check(:state, state, Utils::State::VALID_STATES)
40
+ @state = state
42
41
  @direction = Direction::OUTPUT
43
42
  @file_helper.write_direction(@direction)
44
- @file_helper.write_value(@value)
43
+ @file_helper.write_value(@state)
45
44
  end
46
45
 
47
46
  def output?
@@ -50,70 +49,47 @@ module PiDriver
50
49
 
51
50
  def clear
52
51
  return unless output?
53
- @value = Value::LOW
54
- @file_helper.write_value(@value)
55
- @value
52
+ @state = Utils::State::LOW
53
+ @file_helper.write_value(@state)
54
+ @state
56
55
  end
57
56
 
58
57
  alias_method :off, :clear
59
58
 
60
59
  def clear?
61
- value == Value::LOW
60
+ state == Utils::State::LOW
62
61
  end
63
62
 
64
63
  alias_method :off?, :clear?
65
64
 
66
65
  def set
67
66
  return unless output?
68
- @value = Value::HIGH
69
- @file_helper.write_value(@value)
70
- @value
67
+ @state = Utils::State::HIGH
68
+ @file_helper.write_value(@state)
69
+ @state
71
70
  end
72
71
 
73
72
  alias_method :on, :set
74
73
 
75
74
  def set?
76
- value == Value::HIGH
75
+ state == Utils::State::HIGH
77
76
  end
78
77
 
79
78
  alias_method :on?, :set?
80
79
 
81
- def value
82
- input? ? @file_helper.read_value : @value
80
+ def state
81
+ input? ? @file_helper.read_value : @state
83
82
  end
84
83
 
85
- def interrupt(edge = Edge::RISING)
86
- @argument_helper.check(:edge, edge, Edge::VALID_EDGES)
84
+ def interrupt(edge = Utils::Edge::RISING)
85
+ @argument_helper.check(:edge, edge, Utils::Edge::VALID_EDGES)
87
86
  @edge = edge
88
-
89
- @interrupt_thread = Thread.new do
90
- last_value = @file_helper.read_value
91
- loop do
92
- new_value = @file_helper.read_value
93
- yield if block_given? && interrupted?(new_value, last_value)
94
- last_value = new_value
95
- end
96
- end
87
+ @interrupt = Utils::Interrupt.new(@edge) { @file_helper.read_value }
88
+ @interrupt.start { yield }
97
89
  end
98
90
 
99
91
  def clear_interrupt
100
- @interrupt_thread.kill if @interrupt_thread
101
- end
102
-
103
- private
104
-
105
- def interrupted?(new_value, last_value)
106
- rising_edge = new_value == Value::HIGH && last_value == Value::LOW
107
- falling_edge = new_value == Value::LOW && last_value == Value::HIGH
108
-
109
- case @edge
110
- when :rising
111
- rising_edge
112
- when :falling
113
- falling_edge
114
- when :both
115
- rising_edge || falling_edge
116
- end
92
+ @interrupt.clear if @interrupt
117
93
  end
118
94
  end
119
95
  end
@@ -0,0 +1,65 @@
1
+ module PiDriver
2
+ class Pin
3
+ class Board
4
+ PIN11 = 0
5
+ PIN12 = 1
6
+ PIN13 = 2
7
+ PIN15 = 3
8
+ PIN16 = 4
9
+ PIN18 = 5
10
+ PIN22 = 6
11
+ PIN07 = 7
12
+ PIN03 = 8
13
+ PIN05 = 9
14
+ PIN24 = 10
15
+ PIN26 = 11
16
+ PIN19 = 12
17
+ PIN21 = 13
18
+ PIN23 = 14
19
+ PIN08 = 15
20
+ PIN10 = 16
21
+ PIN29 = 21
22
+ PIN31 = 22
23
+ PIN33 = 23
24
+ PIN35 = 24
25
+ PIN37 = 25
26
+ PIN32 = 26
27
+ PIN36 = 27
28
+ PIN38 = 28
29
+ PIN40 = 29
30
+ PIN27 = 30
31
+ PIN28 = 31
32
+
33
+ VALID_NUMBERS = [
34
+ PIN11,
35
+ PIN12,
36
+ PIN13,
37
+ PIN15,
38
+ PIN16,
39
+ PIN18,
40
+ PIN22,
41
+ PIN07,
42
+ PIN03,
43
+ PIN05,
44
+ PIN24,
45
+ PIN26,
46
+ PIN19,
47
+ PIN21,
48
+ PIN23,
49
+ PIN08,
50
+ PIN10,
51
+ PIN29,
52
+ PIN31,
53
+ PIN33,
54
+ PIN35,
55
+ PIN37,
56
+ PIN32,
57
+ PIN36,
58
+ PIN38,
59
+ PIN40,
60
+ PIN27,
61
+ PIN28
62
+ ]
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,13 @@
1
+ module PiDriver
2
+ class Pin
3
+ class Direction
4
+ INPUT = :in
5
+ OUTPUT = :out
6
+
7
+ VALID_DIRECTIONS = [
8
+ INPUT,
9
+ OUTPUT
10
+ ]
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ module PiDriver
2
+ class Pin
3
+ class DirectoryHelper
4
+ # TODO figure out environment variables for test
5
+ # DIR_BASE = '/sys/class'
6
+ DIR_BASE = File.expand_path '~/pi/gpio/sys/class'
7
+ DIR_GPIO = "#{DIR_BASE}/gpio"
8
+
9
+ def initialize(gpio_number)
10
+ @gpio_number = gpio_number
11
+ end
12
+
13
+ def direction
14
+ "#{dir_pin}/direction"
15
+ end
16
+
17
+ def export
18
+ "#{DIR_GPIO}/export"
19
+ end
20
+
21
+ def value
22
+ "#{dir_pin}/value"
23
+ end
24
+
25
+ private
26
+
27
+ def dir_pin
28
+ "#{DIR_GPIO}/gpio#{@gpio_number}"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'directory_helper'
2
+
3
+ module PiDriver
4
+ class Pin
5
+ class FileHelper
6
+ def initialize(gpio_number)
7
+ @gpio_number = gpio_number
8
+ @directory_helper = DirectoryHelper.new @gpio_number
9
+ end
10
+
11
+ def read_direction
12
+ File.read(@directory_helper.direction).to_sym
13
+ end
14
+
15
+ def read_value
16
+ File.read(@directory_helper.value).to_i
17
+ end
18
+
19
+ def write_direction(direction)
20
+ File.write(@directory_helper.direction, direction)
21
+ end
22
+
23
+ def write_export
24
+ File.write(@directory_helper.export, @gpio_number)
25
+ end
26
+
27
+ def write_value(value)
28
+ File.write(@directory_helper.value, value)
29
+ end
30
+ end
31
+ end
32
+ end