chip-gpio 0.0.6 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chip-gpio/HardwareSpi.rb +170 -0
- data/lib/chip-gpio/{SoftSpi.rb → SoftwareSpi.rb} +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0aadd6093c95dca4fe6b0954d49b95f83939f31
|
4
|
+
data.tar.gz: a0d02a82de5cf742972635168fbebd2b5e5313bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4c585a8fba5f94e479cc001ffabdc8cbd5409f3bfca5051c517063f400e8b39f0ba6609ee769b0b14488d28352d08c5d169be5d188a5c6b78c67cca270b8d66
|
7
|
+
data.tar.gz: '038d8703191146132f6882a9d38cf5906baa3be0b7cd337b77146d3199ddb5a1cc41451b3fb17734561000c357c66a6f70344e246633e670f49558b2f1ecea71'
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module ChipGPIO
|
2
|
+
class HardwareSPI
|
3
|
+
attr_reader :polarity
|
4
|
+
attr_reader :phase
|
5
|
+
attr_reader :word_size
|
6
|
+
attr_reader :lsb_first
|
7
|
+
attr_reader :mode
|
8
|
+
attr_reader :speed_hz
|
9
|
+
|
10
|
+
SPI_MAX_CHUNK_BYTES = 64
|
11
|
+
|
12
|
+
SPI_IOC_RD_MODE = 0x80016b01
|
13
|
+
SPI_IOC_WR_MODE = 0x40016b01
|
14
|
+
SPI_IOC_RD_LSB_FIRST = 0x80016b02
|
15
|
+
SPI_IOC_WR_LSB_FIRST = 0x40016b02
|
16
|
+
SPI_IOC_RD_BITS_PER_WORD = 0x80016b03
|
17
|
+
SPI_IOC_WR_BITS_PER_WORD = 0x40016b03
|
18
|
+
SPI_IOC_RD_MAX_SPEED_HZ = 0x80046b04
|
19
|
+
SPI_IOC_WR_MAX_SPEED_HZ = 0x40046b04
|
20
|
+
SPI_IOC_RD_MODE32 = 0x80046b05
|
21
|
+
SPI_IOC_WR_MODE32 = 0x40046b05
|
22
|
+
|
23
|
+
SPI_IOC_MESSAGE_1 = 0x40206b00 #can only be used to send one spi_ioc_transfer struct at a time
|
24
|
+
|
25
|
+
SPI_CPHA = 0x01
|
26
|
+
SPI_CPOL = 0x02
|
27
|
+
|
28
|
+
def initialize(polarity: 0, phase: 0, word_size: 8, lsb_first: false)
|
29
|
+
@polarity = polarity
|
30
|
+
@phase = phase
|
31
|
+
@word_size = word_size
|
32
|
+
@lsb_first = lsb_first
|
33
|
+
@speed_hz = 1000000 #TODO Configurable parameter
|
34
|
+
|
35
|
+
@device = open("/dev/spidev32766.0", File::RDWR)
|
36
|
+
|
37
|
+
@mode = 0
|
38
|
+
@mode = @mode | 0x01 if (phase == 1)
|
39
|
+
@mode = @mode | 0x02 if (polarity == 1)
|
40
|
+
|
41
|
+
write_u8(SPI_IOC_WR_MODE, @mode)
|
42
|
+
write_u8(SPI_IOC_WR_LSB_FIRST, (@lsb_first ? 1 : 0))
|
43
|
+
write_u32(SPI_IOC_WR_MAX_SPEED_HZ, @speed_hz)
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def close()
|
48
|
+
@device.close()
|
49
|
+
end
|
50
|
+
|
51
|
+
def read_u8(msg)
|
52
|
+
value_packed = [0].pack("C")
|
53
|
+
@device.ioctl(msg, value_packed)
|
54
|
+
return value_packed.unpack("C")[0]
|
55
|
+
end
|
56
|
+
|
57
|
+
def write_u8(msg, value)
|
58
|
+
value_packed = [value].pack("C")
|
59
|
+
@device.ioctl(msg, value_packed)
|
60
|
+
end
|
61
|
+
|
62
|
+
def read_u32(msg)
|
63
|
+
value_packed = [0].pack("L")
|
64
|
+
@device.ioctl(msg, value_packed)
|
65
|
+
return value_packed.unpack("L")[0]
|
66
|
+
end
|
67
|
+
|
68
|
+
def write_u32(msg, value)
|
69
|
+
value_packed = [value].pack("L")
|
70
|
+
@device.ioctl(msg, value_packed)
|
71
|
+
end
|
72
|
+
|
73
|
+
def break_words_into_nibbles(words: [])
|
74
|
+
nibbles_per_word = @word_size / 4
|
75
|
+
|
76
|
+
#for each word, output each nibble individually
|
77
|
+
#(shifting by 4 each time since a nibble is 4 bits)
|
78
|
+
words.each do |w|
|
79
|
+
|
80
|
+
#this is basically the reverse of nibbles_per_word.times
|
81
|
+
#we reverse it because we want to start at the most-significant nibble
|
82
|
+
#which will be shifted the most times
|
83
|
+
#
|
84
|
+
#since we want to end up at 0, subtract one from nibbles_per_word
|
85
|
+
#so we don't get an extra
|
86
|
+
(nibbles_per_word - 1).downto(0).each do |i|
|
87
|
+
yield w, ((w >> (i * 4)) & 0xf)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def pack_words_into_bytes(words: [])
|
93
|
+
nibbles_per_word = @word_size / 4
|
94
|
+
|
95
|
+
bytes = []
|
96
|
+
current_byte = 0
|
97
|
+
new_byte = true
|
98
|
+
|
99
|
+
break_words_into_nibbles(words: words) do |current_word, current_nibble|
|
100
|
+
if new_byte
|
101
|
+
new_byte = false
|
102
|
+
current_byte = current_byte | (current_nibble << 4)
|
103
|
+
else
|
104
|
+
current_byte = current_byte | current_nibble
|
105
|
+
|
106
|
+
bytes << current_byte
|
107
|
+
current_byte = 0
|
108
|
+
new_byte = true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
return bytes
|
113
|
+
end
|
114
|
+
|
115
|
+
def transfer_bytes(bytes: [])
|
116
|
+
# http://stackoverflow.com/questions/11949538/pointers-to-buffer-in-ioctl-call
|
117
|
+
raise "Too many bytes sent to transfer_bytes" if bytes.size > SPI_MAX_CHUNK_BYTES
|
118
|
+
|
119
|
+
#begin spi_ioc_transfer struct (cat /usr/include/linux/spi/spidev.h)
|
120
|
+
tx_buff = bytes.pack("C*")
|
121
|
+
rx_buff = (Array.new(bytes.size) { 0 }).pack("C*")
|
122
|
+
|
123
|
+
tx_buff_pointer = [tx_buff].pack("P").unpack("L!")[0] #u64 (zero-extended pointer)
|
124
|
+
rx_buff_pointer = [rx_buff].pack("P").unpack("L!")[0] #u64 (zero-extended pointer)
|
125
|
+
|
126
|
+
|
127
|
+
buff_len = bytes.size #u32
|
128
|
+
speed_hz = @speed_hz #u32
|
129
|
+
|
130
|
+
delay_usecs = 0 #u16
|
131
|
+
bits_per_word = 8 #u8
|
132
|
+
cs_change = 0 #u8
|
133
|
+
tx_nbits = 0 #u8
|
134
|
+
rx_nbits = 0 #u8
|
135
|
+
pad = 0 #u16
|
136
|
+
|
137
|
+
struct_array = [tx_buff_pointer, rx_buff_pointer, buff_len, speed_hz, delay_usecs, bits_per_word, cs_change, tx_nbits, rx_nbits, pad]
|
138
|
+
struct_packed = struct_array.pack("QQLLSCCCCS")
|
139
|
+
#end spi_ioc_transfer struct
|
140
|
+
|
141
|
+
@device.ioctl(SPI_IOC_MESSAGE_1, struct_packed)
|
142
|
+
|
143
|
+
return rx_buff.unpack("C*")
|
144
|
+
end
|
145
|
+
|
146
|
+
def transfer_data(words: [])
|
147
|
+
|
148
|
+
bytes_to_transfer = pack_words_into_bytes(words: words)
|
149
|
+
|
150
|
+
result = []
|
151
|
+
|
152
|
+
bytes_to_transfer.each_slice(SPI_MAX_CHUNK_BYTES) do |chunk_bytes|
|
153
|
+
result = result + transfer_bytes(bytes: chunk_bytes)
|
154
|
+
end
|
155
|
+
|
156
|
+
return result
|
157
|
+
end
|
158
|
+
|
159
|
+
def test()
|
160
|
+
words = []
|
161
|
+
24.times { |i| words << 0 }
|
162
|
+
|
163
|
+
transfer_data(words: words)
|
164
|
+
end
|
165
|
+
|
166
|
+
def to_s
|
167
|
+
return "\#<ChipGPIO:HardwareSPI mode=#{@mode} device=#{@device.path} word_size=#{@word_size} lsb_first=#{@lsb_first}>"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chip-gpio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A ruby gem to control the IO hardware the CHIP computer
|
14
14
|
email: james@jameswilliams.me
|
@@ -18,8 +18,9 @@ extra_rdoc_files: []
|
|
18
18
|
files:
|
19
19
|
- README.md
|
20
20
|
- lib/chip-gpio.rb
|
21
|
+
- lib/chip-gpio/HardwareSpi.rb
|
21
22
|
- lib/chip-gpio/Pin.rb
|
22
|
-
- lib/chip-gpio/
|
23
|
+
- lib/chip-gpio/SoftwareSpi.rb
|
23
24
|
homepage: http://github.com/willia4/chip-gpio
|
24
25
|
licenses:
|
25
26
|
- MIT
|