chip-gpio 0.0.6 → 0.1.2
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 +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
|