mruby-linux-spi 0.9.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4a72961a5cd63b9763984c28407d942c81de8311e0780eb24e9bc371aedeaf56
4
+ data.tar.gz: 07034c750af72824ff3436e7ef44435c69ccb2b5b78cda3d25fde26238a14cab
5
+ SHA512:
6
+ metadata.gz: 79d7b82d3217cbec07af1551c33c3af4404423913cdd986ee14367bf685c77432d62ce24cdb09012488bc28fe31b5a40624c0fa177beb99d8a2585b7532f30e8
7
+ data.tar.gz: 33b8175d33eb5a0d29db8b30689f1108bf7f8b4f2c567ed9c155b285564c267e7acf3fa9c99daed5c5a2b6f4a2d6a54e02f9f65abdbbbd7452993ed731ad0472
data/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2023, Shimane IT Open-Innovation Center.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # SPI class using Linux spidev.
2
+
3
+ ![ADXL345 Demo](img/adxl345_demo.gif) >> [source code](test/ADXL345_Accelerometer.rb)
4
+
5
+ ## Overview
6
+
7
+ This is an implementation of the SPI class library for Linux.
8
+ Follows [mruby, mruby/c common I/O API guidelines.](https://github.com/mruby/microcontroller-peripheral-interface-guide)
9
+
10
+ This library uses the Linux spidev device driver.
11
+
12
+ ## Installation
13
+
14
+ $ gem install mruby-linux-spi
15
+
16
+
17
+ ## Features
18
+
19
+ * This class defines only master devices and transfers in 8-bit units.
20
+ * The Chip Select (CS/SS) will be managed spidev device driver automatically.
21
+
22
+ ## Usage
23
+
24
+ about RaspberryPi...
25
+
26
+ ```
27
+ # Connect pin #19 as MOSI, #21 as MISO, #23 as SCLK, #24 as CS.
28
+
29
+ require "mruby/spi"
30
+
31
+ # create instance
32
+ spi = SPI.new()
33
+
34
+ # read 4 bytes (send out 0x00 x 4bytes)
35
+ s = spi.read(4)
36
+ ```
37
+
38
+ Other case, see original guidelines.
39
+ https://github.com/mruby/microcontroller-peripheral-interface-guide/blob/main/mruby_io_SPI_en.md
40
+
41
+
42
+ ## Licence
43
+
44
+ BSD 3-Clause License. see LICENSE file.
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SPI
4
+ VERSION = "0.9.0"
5
+ end
data/lib/mruby/spi.rb ADDED
@@ -0,0 +1,240 @@
1
+ #
2
+ # SPI class using Linux spidev.
3
+ #
4
+ # Copyright (c) 2023 Shimane IT Open-Innovation Center.
5
+ #
6
+ # see: LICENSE file.
7
+ # see: https://github.com/mruby/microcontroller-peripheral-interface-guide/blob/main/mruby_io_SPI_en.md
8
+ #
9
+ # frozen_string_literal: true
10
+ #
11
+
12
+ require_relative "spi/version"
13
+
14
+ ##
15
+ # SPI namespace
16
+ #
17
+ module SPI
18
+
19
+ MSB_FIRST = 0
20
+ LSB_FIRST = 1
21
+
22
+
23
+ ##
24
+ # constructor
25
+ #
26
+ #@see SPI::LinuxSPIdev.initialize
27
+ #
28
+ def self.new(node = "/dev/spidev0.0", frequency:1_000_000, mode:0, first_bit:SPI::MSB_FIRST )
29
+ SPI::LinuxSPIdev.new(node, frequency, mode, first_bit)
30
+ end
31
+ end
32
+
33
+
34
+ ##
35
+ # Linux SPI Device driver
36
+ #
37
+ class SPI::LinuxSPIdev
38
+
39
+ # Constants
40
+ # see: /usr/include/linux/spi/spidev.h, /usr/include/asm-generic/ioctl.h
41
+ IOC_NONE = 0
42
+ IOC_WRITE = 1
43
+ IOC_READ = 2
44
+ SPI_IOC_MAGIC = 'k'.ord
45
+
46
+ # Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) (limited to 8 bits)
47
+ # define SPI_IOC_RD_MODE _IOR(SPI_IOC_MAGIC, 1, __u8)
48
+ # define SPI_IOC_WR_MODE _IOW(SPI_IOC_MAGIC, 1, __u8)
49
+ # _IOx( type, nr, size ) is bit mapped [RW][size:14][type:8][nr:8]
50
+ # dir | size | type | nr
51
+ SPI_IOC_RD_MODE = IOC_READ << 30 | 1 << 16 | SPI_IOC_MAGIC << 8 | 1
52
+ SPI_IOC_WR_MODE = IOC_WRITE << 30 | 1 << 16 | SPI_IOC_MAGIC << 8 | 1
53
+
54
+ # Read / Write SPI bit justification
55
+ # define SPI_IOC_RD_LSB_FIRST _IOR(SPI_IOC_MAGIC, 2, __u8)
56
+ # define SPI_IOC_WR_LSB_FIRST _IOW(SPI_IOC_MAGIC, 2, __u8)
57
+ # dir | size | type | nr
58
+ SPI_IOC_RD_LSB_FIRST = IOC_READ << 30 | 1 << 16 | SPI_IOC_MAGIC << 8 | 2
59
+ SPI_IOC_WR_LSB_FIRST = IOC_WRITE << 30 | 1 << 16 | SPI_IOC_MAGIC << 8 | 2
60
+
61
+ # Read / Write SPI device word length (1..N)
62
+ # define SPI_IOC_RD_BITS_PER_WORD _IOR(SPI_IOC_MAGIC, 3, __u8)
63
+ # define SPI_IOC_WR_BITS_PER_WORD _IOW(SPI_IOC_MAGIC, 3, __u8)
64
+ # dir | size | type | nr
65
+ SPI_IOC_RD_BITS_PER_WORD = IOC_READ << 30 | 1 << 16 | SPI_IOC_MAGIC << 8 | 3
66
+ SPI_IOC_WR_BITS_PER_WORD = IOC_WRITE << 30 | 1 << 16 | SPI_IOC_MAGIC << 8 | 3
67
+
68
+ # Read / Write SPI device default max speed hz
69
+ # define SPI_IOC_RD_MAX_SPEED_HZ _IOR(SPI_IOC_MAGIC, 4, __u32)
70
+ # define SPI_IOC_WR_MAX_SPEED_HZ _IOW(SPI_IOC_MAGIC, 4, __u32)
71
+ # dir | size | type | nr
72
+ SPI_IOC_RD_MAX_SPEED_HZ = IOC_READ << 30 | 4 << 16 | SPI_IOC_MAGIC << 8 | 4
73
+ SPI_IOC_WR_MAX_SPEED_HZ = IOC_WRITE << 30 | 4 << 16 | SPI_IOC_MAGIC << 8 | 4
74
+
75
+ # define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
76
+ # char[SPI_MSGSIZE(1) is 32 bytes.
77
+ # NOTE: struct layout is the same in 64bit and 32bit userspace.
78
+ # dir | size | type | nr
79
+ SPI_IOC_MESSAGE = IOC_WRITE << 30 |32 << 16 | SPI_IOC_MAGIC << 8 | 0
80
+
81
+
82
+ ##
83
+ # constructor
84
+ #
85
+ #@param [String] node device node of SPI
86
+ #@param [Integer] frequency SCLK frequency.
87
+ #@param [Integer] mode SPI mode (0..3)
88
+ #@param [Constant] first_bit MSB_FIRST or LSB_FIRST
89
+ #@see SPI.new
90
+ #
91
+ def initialize(node, frequency, mode, first_bit)
92
+ @device = File.open(node, "r+:ASCII-8BIT")
93
+
94
+ _set_max_speed_hz( frequency )
95
+ _set_mode( mode )
96
+ _set_lsb_first( first_bit )
97
+ end
98
+
99
+
100
+ ##
101
+ # Changes the operating mode (parameters) of the SPI.
102
+ #
103
+ #@param [Integer] frequency SCLK frequency.
104
+ #@param [Integer] mode SPI mode (0..3)
105
+ #@return [void]
106
+ #
107
+ def setmode( frequency:nil, mode:nil )
108
+ _set_max_speed_hz( frequency ) if frequency
109
+ _set_mode( mode ) if mode
110
+ end
111
+
112
+
113
+ ##
114
+ # Reads data of read_bytes bytes from the SPI bus.
115
+ #
116
+ #@param [Integer] read_bytes read bytes.
117
+ #@return [String] reading datas.
118
+ #
119
+ def read( read_bytes )
120
+ @device.sysread( read_bytes )
121
+ end
122
+
123
+
124
+ ##
125
+ # Outputs data specified in outputs to the SPI bus.
126
+ #
127
+ #@param [Integer,String,Array<Integer>] outputs output data.
128
+ #@return [nil]
129
+ #
130
+ def write( *outputs )
131
+ send_data = _rebuild_output_data( outputs )
132
+ @device.syswrite( send_data )
133
+ return nil
134
+ end
135
+
136
+
137
+ ##
138
+ # Outputs data specified in outputs to the SPI bus while
139
+ # simultaneously reading data (General-purpose transfer).
140
+ #
141
+ #@param [Integer,String,Array<Integer>] outputs output data.
142
+ #@param [Integer] additional_read_bytes additional read bytes
143
+ #@return [String] reading datas.
144
+ #
145
+ def transfer( outputs, additional_read_bytes = 0 )
146
+
147
+ # prepare the send buffer and receive buffer.
148
+ send_data = _rebuild_output_data( [outputs] )
149
+ len = send_data.size
150
+ if additional_read_bytes > 0
151
+ send_data << ("\x00".b * additional_read_bytes)
152
+ len += additional_read_bytes
153
+ end
154
+ recv_data = "\x00".b * len
155
+
156
+ # prepare the struct spi_ioc_transfer. (spidev.h)
157
+ arg = [ [send_data].pack("P").unpack1("J"), # __u64 tx_buf;
158
+ [recv_data].pack("P").unpack1("J"), # __u64 rx_buf;
159
+
160
+ len, # __u32 len;
161
+ 0, # __u32 speed_hz;
162
+
163
+ 0, # __u16 delay_usecs;
164
+ 0, # __u8 bits_per_word;
165
+ 0, # __u8 cs_change;
166
+ 0, # __u8 tx_nbits;
167
+ 0, # __u8 rx_nbits;
168
+ 0, # __u8 word_delay_usecs;
169
+ 0, # __u8 pad;
170
+ ].pack("QQLLSCCCCCC")
171
+
172
+ # trigger IOCTL.
173
+ @device.ioctl( SPI_IOC_MESSAGE, arg )
174
+ return recv_data
175
+ end
176
+
177
+
178
+ private
179
+ def _get_mode()
180
+ arg = "\x00".b
181
+ @device.ioctl( SPI_IOC_RD_MODE, arg )
182
+ return arg.unpack("C")[0]
183
+ end
184
+
185
+ def _set_mode( mode )
186
+ arg = [mode].pack("C")
187
+ @device.ioctl( SPI_IOC_WR_MODE, arg )
188
+ end
189
+
190
+ def _get_lsb_first()
191
+ arg = "\x00".b
192
+ @device.ioctl( SPI_IOC_RD_LSB_FIRST, arg )
193
+ return arg.unpack("C")[0]
194
+ end
195
+
196
+ def _set_lsb_first( flag )
197
+ #(note) Legal operation could not be confirmed with RasPi OS ioctl.
198
+ arg = [flag].pack("C")
199
+ @device.ioctl( SPI_IOC_WR_LSB_FIRST, arg )
200
+ end
201
+
202
+ def _get_bits_per_word()
203
+ arg = "\x00".b
204
+ @device.ioctl( SPI_IOC_RD_BITS_PER_WORD, arg )
205
+ return arg.unpack("C")[0]
206
+ end
207
+
208
+ def _set_bits_per_word( bits_per_word )
209
+ arg = [bits_per_word].pack("C")
210
+ @device.ioctl( SPI_IOC_WR_BITS_PER_WORD, arg )
211
+ end
212
+
213
+ def _get_max_speed_hz()
214
+ arg = "\x00\x00\x00\x00".b
215
+ @device.ioctl( SPI_IOC_RD_MAX_SPEED_HZ, arg )
216
+ return arg.unpack("L")[0]
217
+ end
218
+
219
+ def _set_max_speed_hz( freq )
220
+ arg = [freq].pack("L")
221
+ @device.ioctl( SPI_IOC_WR_MAX_SPEED_HZ, arg )
222
+ end
223
+
224
+ def _rebuild_output_data( arg )
225
+ data = "".b
226
+ arg.flatten.each {|d|
227
+ case d
228
+ when Integer
229
+ data << d.chr
230
+ when String
231
+ data << d.force_encoding(Encoding::ASCII_8BIT)
232
+ else
233
+ raise ArgumentError
234
+ end
235
+ }
236
+
237
+ return data
238
+ end
239
+
240
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mruby-linux-spi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - HirohitoHigashi
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-10-13 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - higashi@s-itoc.jp
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - LICENSE
21
+ - README.md
22
+ - lib/mruby/spi.rb
23
+ - lib/mruby/spi/version.rb
24
+ homepage: https://github.com/HirohitoHigashi/mruby-mio/tree/main/mruby-linux-spi
25
+ licenses: []
26
+ metadata:
27
+ homepage_uri: https://github.com/HirohitoHigashi/mruby-mio/tree/main/mruby-linux-spi
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 2.6.0
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubygems_version: 3.4.13
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: SPI bus driver class library using Linux spidev.
47
+ test_files: []