pigpio_ffi 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +63 -0
- data/lib/pigpio_ffi/advanced.rb +29 -0
- data/lib/pigpio_ffi/basic.rb +19 -0
- data/lib/pigpio_ffi/configuration.rb +52 -0
- data/lib/pigpio_ffi/essential.rb +7 -0
- data/lib/pigpio_ffi/i2c.rb +87 -0
- data/lib/pigpio_ffi/intermediate.rb +64 -0
- data/lib/pigpio_ffi/pwm.rb +25 -0
- data/lib/pigpio_ffi/servo.rb +10 -0
- data/lib/pigpio_ffi/spi.rb +87 -0
- data/lib/pigpio_ffi/utilities.rb +25 -0
- data/lib/pigpio_ffi/version.rb +3 -0
- data/lib/pigpio_ffi/waves.rb +99 -0
- data/lib/pigpio_ffi.rb +40 -0
- data/pigpio_ffi.gemspec +16 -0
- metadata +74 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7df185ca3334d723f7de61a087ae7ead59cab8ff44897de6a9d6cf17596ae86e
|
4
|
+
data.tar.gz: abacbdd2ba20c599513ca602d99f609fddec7f284a838d60511772c97a6d266d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2b3f4222a72177044c47e949fe857dc6a9e03fa4922c6d5e1f8be19c622e421eebeb64bac0a4ac25d190c754c4789cd847424a6c02e779f44adebd6231022046
|
7
|
+
data.tar.gz: 6b0b5f1efe4dfdb8c6a6556b9c67cff2aaca4f56c2466a5a68436eb12e11515f06cfbf9a0460e922e2a129cc60f4a002f1a4f1f26cd0469d99ebc4e995415707
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 dino-rb
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# pigpio_ffi 0.1.0
|
2
|
+
|
3
|
+
This gem uses [FFI](https://github.com/ffi/ffi) to provide Ruby method bindings for the [pigpio](https://abyz.me.uk/rpi/pigpio/index.html) C library. This makes the Raspberry Pi GPIO pins usable in Ruby.
|
4
|
+
|
5
|
+
NOTE: This is for Ruby on Linux, not for the Raspberry Pi Pico (W).
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Install pigpio with:
|
10
|
+
```shell
|
11
|
+
sudo apt-get install pigpio
|
12
|
+
```
|
13
|
+
|
14
|
+
Install this gem as root:
|
15
|
+
```shell
|
16
|
+
sudo gem install pigpio_ffi
|
17
|
+
```
|
18
|
+
|
19
|
+
Ruby scripts need to be run as root:
|
20
|
+
```shell
|
21
|
+
sudo ruby my_script.rb
|
22
|
+
```
|
23
|
+
|
24
|
+
## Example
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
require 'pigpio_ffi'
|
28
|
+
|
29
|
+
PiGPIO.gpioInitialise
|
30
|
+
PiGPIO.gpioSetMode(4, 1)
|
31
|
+
|
32
|
+
10.times do
|
33
|
+
PiGPIO.gpioWrite(4, 1)
|
34
|
+
sleep 0.5
|
35
|
+
PiGPIO.gpioWrite(4, 0)
|
36
|
+
sleep 0.5
|
37
|
+
end
|
38
|
+
|
39
|
+
# This must be called or the script will block forever.
|
40
|
+
PiGPIO.gpioTerminate
|
41
|
+
```
|
42
|
+
This will blink an LED attached to GPIO 4, every half second, for 10 seconds total.
|
43
|
+
|
44
|
+
## Mapped Features
|
45
|
+
|
46
|
+
- Basic GPIO (set mode, read, write, alert on change)
|
47
|
+
- PWM (bitbang)
|
48
|
+
- Servo (bitbang)
|
49
|
+
- Waves (infrared and other protocols)
|
50
|
+
- I2C (still untested)
|
51
|
+
- SPI (still untested)
|
52
|
+
|
53
|
+
## Documentation
|
54
|
+
|
55
|
+
As much as possible, the class methods of `PiGPIO` follow the function names and argument formats of the pigpio C functions. These can be found in its documentation, located [here](https://abyz.me.uk/rpi/pigpio/download.html).
|
56
|
+
|
57
|
+
**Exceptions**:
|
58
|
+
|
59
|
+
- Functions where one argument is a callback function. These translate to Ruby methods that take a block.
|
60
|
+
- Functions that take arrays and their length as separate arguments. These translate to Ruby methods where the length argument is omitted.
|
61
|
+
- Not all functions are mapped. I left out anything Ruby (or an existing gem) can already do, or any complex data processing that would be easier in Ruby anyway.
|
62
|
+
|
63
|
+
TODO: List methods with different interfaces, and unmapped methods here.
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PiGPIO
|
2
|
+
extend FFI::Library
|
3
|
+
ffi_lib 'pigpio'
|
4
|
+
|
5
|
+
# gpioNotifyOpen not mapped.
|
6
|
+
# gpioNotifyClose not mapped.
|
7
|
+
# gpioNotifyOpenWithSize not mapped.
|
8
|
+
# gpioNotifyBegin not mapped.
|
9
|
+
# gpioNotifyPause not mapped.
|
10
|
+
|
11
|
+
# gpioHardwareClock not mapped.
|
12
|
+
# gpioHardwarePWM not mapped.
|
13
|
+
|
14
|
+
# Args: gpio, steady time
|
15
|
+
attach_function :gpioGlitchFilter, [:uint, :uint], :int
|
16
|
+
|
17
|
+
# Args: gpio, steady time, active time
|
18
|
+
attach_function :gpioNoiseFilter, [:uint, :uint, :uint], :int
|
19
|
+
|
20
|
+
# gpioSetPad not mapped.
|
21
|
+
# gpioGetPad not mapped.
|
22
|
+
# shell not mapped.
|
23
|
+
# gpioSetISRFunc not mapped.
|
24
|
+
# gpioSetISRFuncEx not mapped.
|
25
|
+
# gpioSetSignalFunc not mapped.
|
26
|
+
# gpioSetSignalFuncEx not mapped.
|
27
|
+
# gpioSetGetSamplesFunc not mapped.
|
28
|
+
# gpioSetGetSamplesFuncEx not mapped.
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PiGPIO
|
2
|
+
extend FFI::Library
|
3
|
+
ffi_lib 'pigpio'
|
4
|
+
|
5
|
+
# Args: gpio, mode (0 = input, 1 = output, 2-7 = alternative)
|
6
|
+
attach_function :gpioSetMode, [:uint, :uint], :int
|
7
|
+
|
8
|
+
# Args: gpio
|
9
|
+
attach_function :gpioGetMode, [:uint], :int
|
10
|
+
|
11
|
+
# Args, gpio, pud (0 = off, 1 = pulldown, 2 = pullup)
|
12
|
+
attach_function :gpioSetPullUpDown, [:uint, :uint], :int
|
13
|
+
|
14
|
+
# Args: gpio
|
15
|
+
attach_function :gpioRead, [:uint], :int
|
16
|
+
|
17
|
+
# Args: gpio, level
|
18
|
+
attach_function :gpioWrite, [:uint, :uint], :int
|
19
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module PiGPIO
|
2
|
+
extend FFI::Library
|
3
|
+
ffi_lib 'pigpio'
|
4
|
+
|
5
|
+
#
|
6
|
+
# GPIO callbacks do not trigger immediately.
|
7
|
+
# This batches them every X milliseconds. Defaults to 120.
|
8
|
+
#
|
9
|
+
# NOTE: Must be called before #gpioInitialise.
|
10
|
+
#
|
11
|
+
# Args: buffer in milliseconds
|
12
|
+
attach_function :gpioCfgBufferSize, [:uint], :int
|
13
|
+
|
14
|
+
#
|
15
|
+
# Configure the sampling rate for GPIO pins in microseconds.
|
16
|
+
# Defaults to 5us using the PCM peripheral.
|
17
|
+
#
|
18
|
+
# NOTE: Must be called before #gpioInitialise.
|
19
|
+
#
|
20
|
+
# Args: microseconds, peripheral (0=PWM, 1=PCM), source (deprecated, give 0)
|
21
|
+
attach_function :gpioCfgClock, [:uint, :uint, :uint], :int
|
22
|
+
|
23
|
+
# gpioCfgDMAchannel is deprecated.
|
24
|
+
|
25
|
+
#
|
26
|
+
# Configure pigpio to use specified DMA channels (0-14).
|
27
|
+
# Defaults:
|
28
|
+
# BCM2711: 7 (primary), 6 (secondary)
|
29
|
+
# Others: 14 (primary), 6 (secondary)
|
30
|
+
#
|
31
|
+
# NOTE: Must be called before #gpioInitialise.
|
32
|
+
#
|
33
|
+
# Args: DMA channel number
|
34
|
+
attach_function :gpioCfgDMAchannels, [:uint], :int
|
35
|
+
|
36
|
+
# gpioCfgPermission not mapped.
|
37
|
+
# gpioCfgSocketPort not mapped.
|
38
|
+
# gpioCfgInterfaces not mapped.
|
39
|
+
|
40
|
+
#
|
41
|
+
# NOTE: Must be called before #gpioInitialise.
|
42
|
+
#
|
43
|
+
# Args: memAllocMode (0-2)
|
44
|
+
# 0 = AUTO
|
45
|
+
# 1 = PAGEMAP
|
46
|
+
# 2 = MAILBOX
|
47
|
+
attach_function :gpioCfgMemAlloc, [:uint], :int
|
48
|
+
|
49
|
+
# gpioCfgNetAddr not mapped.
|
50
|
+
# gpioCfgGetInternals not mapped.
|
51
|
+
# gpioCfgSetInternals not mapped.
|
52
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module PiGPIO
|
2
|
+
extend FFI::Library
|
3
|
+
ffi_lib 'pigpio'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Open a handle for I2C device at specified address (0-127).
|
7
|
+
#
|
8
|
+
# Args: i2cBus, i2cAddr, i2cFlags (set to 0)
|
9
|
+
# Returns: handle as integer
|
10
|
+
attach_function :i2cOpen, [:uint, :uint, :uint], :int
|
11
|
+
|
12
|
+
#
|
13
|
+
# Close an I2C device handle.
|
14
|
+
#
|
15
|
+
# Args: handle
|
16
|
+
attach_function :i2cClose, [:uint], :int
|
17
|
+
|
18
|
+
# i2cWriteQuick not mapped.
|
19
|
+
|
20
|
+
# Args: handle, byte
|
21
|
+
attach_function :i2cWriteByte, [:uint, :uint8], :int
|
22
|
+
|
23
|
+
# Args: handle
|
24
|
+
attach_function :i2cReadByte, [:uint], :int
|
25
|
+
|
26
|
+
# i2cWriteByteData not mapped.
|
27
|
+
# i2cWriteWordData not mapped.
|
28
|
+
# i2cReadByteData not mapped.
|
29
|
+
# i2cReadWordData not mapped.
|
30
|
+
# i2cProcessCall not mapped.
|
31
|
+
# i2cWriteBlockData not mapped.
|
32
|
+
# i2cReadBlockData not mapped.
|
33
|
+
# i2cBlockProcessCall not mapped.
|
34
|
+
|
35
|
+
#
|
36
|
+
# Read up to 32 bytes from a given I2C address (as handle), and start register.
|
37
|
+
#
|
38
|
+
# Don't call this directly.
|
39
|
+
attach_function :_i2cReadI2CBlockData, :i2cReadI2CBlockData, [:uint, :uint, :pointer], :int
|
40
|
+
#
|
41
|
+
# Call this instead.
|
42
|
+
def self.i2cReadI2CBlockData(handle, start_register, length)
|
43
|
+
raise ArgumentError, "Cannot read more than 32 I2C bytes" if length > 32
|
44
|
+
buffer_pointer = FFI::MemoryPointer.new(:uint8, length)
|
45
|
+
|
46
|
+
# Read it and convert it to a Ruby array.
|
47
|
+
self._i2cReadI2CBlockData(handle, start_register, buffer_pointer)
|
48
|
+
bytes = buffer_pointer.read_array_of_type(:uint8, length)
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Write up to 32 bytes to a given I2C address (as handle), and start register.
|
53
|
+
#
|
54
|
+
# Don't call this directly.
|
55
|
+
attach_function :_i2cWriteI2CBlockData, :i2cWriteI2CBlockData, [:uint, :uint, :pointer], :int
|
56
|
+
#
|
57
|
+
# Call this instead.
|
58
|
+
def self.i2cWriteI2CBlockData(handle, start_register, byte_array)
|
59
|
+
# Do some validation.
|
60
|
+
raise ArgumentError, "Cannot write more than 32 I2C bytes" if byte_array > 32
|
61
|
+
byte_array.each do |element|
|
62
|
+
raise ArgumentError, "Byte values must be within 0x00 and 0xFF" if (element > 0xFF || element < 0x00)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Copy the array to the pointer location.
|
66
|
+
buffer_pointer = FFI::MemoryPointer.new(:uint8, byte_array.length)
|
67
|
+
buffer_pointer.write_array_of_type(:uint8, byte_array)
|
68
|
+
|
69
|
+
# Write it.
|
70
|
+
self._i2cReadI2CBlockData(handle, start_register, buffer_pointer)
|
71
|
+
end
|
72
|
+
|
73
|
+
# i2cReadDevice not mapped.
|
74
|
+
# i2cWriteDevice not mapped.
|
75
|
+
|
76
|
+
#
|
77
|
+
# When enabled, this sends repeated start bits instead of stop.
|
78
|
+
#
|
79
|
+
# Args: setting (0=off, 1=on)
|
80
|
+
attach_function :i2cSwitchCombined, [:uint], :void
|
81
|
+
|
82
|
+
# i2cSegments not mapped.
|
83
|
+
# i2cZip not mapped.
|
84
|
+
# bbI2COpen not mapped yet.
|
85
|
+
# bbI2CClose not mapped yet.
|
86
|
+
# bbI2CZip not mapped yet.
|
87
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module PiGPIO
|
2
|
+
extend FFI::Library
|
3
|
+
ffi_lib 'pigpio'
|
4
|
+
|
5
|
+
# Pulse a GPIO by holding it at level for pulse length, then resetting to not level.
|
6
|
+
# Args: gpio, pulse length, level
|
7
|
+
attach_function :gpioTrigger, [:uint, :uint, :uint], :int
|
8
|
+
|
9
|
+
# gpioSetWatchdog not mapped.
|
10
|
+
|
11
|
+
# Returns: bit mask of GPIO states
|
12
|
+
attach_function :gpioRead_Bits_0_31, [], :uint32
|
13
|
+
|
14
|
+
# Returns: bit mask of GPIO states
|
15
|
+
attach_function :gpioRead_Bits_32_53, [], :uint32
|
16
|
+
|
17
|
+
# Arg: bit mask of pins to clear (1 = clear, 0 = leave alone)
|
18
|
+
attach_function :gpioWrite_Bits_0_31_Clear, [:uint32], :int
|
19
|
+
|
20
|
+
# Arg: bit mask of pins to clear (1 = clear, 0 = leave alone)
|
21
|
+
attach_function :gpioWrite_Bits_32_53_Clear, [:uint32], :int
|
22
|
+
|
23
|
+
# Arg: bit mask of pins to clear (1 = set, 0 = leave alone)
|
24
|
+
attach_function :gpioWrite_Bits_0_31_Set, [:uint32], :int
|
25
|
+
|
26
|
+
# Arg: bit mask of pins to clear (1 = set, 0 = leave alone)
|
27
|
+
attach_function :gpioWrite_Bits_32_53_Set, [:uint32], :int
|
28
|
+
|
29
|
+
#
|
30
|
+
# Observe/listen for changes on a GPIO.
|
31
|
+
# NOTE: Use the last method defined in this section.
|
32
|
+
#
|
33
|
+
# Callback receives args: gpio, value, tick (microseconds since boot, 72 minute overflow)
|
34
|
+
callback :alert_callback, [:uint, :uint, :uint], :void
|
35
|
+
#
|
36
|
+
# Args: gpio, callback as proc (nil to disable)
|
37
|
+
attach_function :_gpioSetAlertFunc, :gpioSetAlertFunc, [:uint, :alert_callback], :int
|
38
|
+
#
|
39
|
+
# Call this one with a block.
|
40
|
+
def self.gpioSetAlertFunc(gpio, &block)
|
41
|
+
self._gpioSetAlertFunc(gpio, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
# gpioSetAlertFuncEx not mapped.
|
45
|
+
|
46
|
+
#
|
47
|
+
# Register a callback with one of the hardware timers (0-9).
|
48
|
+
# NOTE: Use the last method defined in this section.
|
49
|
+
#
|
50
|
+
# Callback receives no args.
|
51
|
+
callback :alert_callback, [], :void
|
52
|
+
#
|
53
|
+
# Args: timer index, millisecond interval, callback as proc (nil to disable)
|
54
|
+
attach_function :_gpioSetTimerFunc, :gpioSetTimerFunc, [:uint, :uint], :int
|
55
|
+
#
|
56
|
+
# Call this one with a block.
|
57
|
+
def self.gpioSetTimerFunc(timer, millis, &block)
|
58
|
+
self._gpioSetTimerFunc(gpio, millis, &block)
|
59
|
+
end
|
60
|
+
|
61
|
+
# gpioSetTimerFuncEx not mapped.
|
62
|
+
# gpioStartThread not mapped.
|
63
|
+
# gpioStopThread not mapped.
|
64
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module PiGPIO
|
2
|
+
extend FFI::Library
|
3
|
+
ffi_lib 'pigpio'
|
4
|
+
|
5
|
+
# Args: gpio, dutycycle (0-range)
|
6
|
+
attach_function :gpioPWM, [:uint, :uint], :int
|
7
|
+
|
8
|
+
# Args: gpio
|
9
|
+
attach_function :gpioGetPWMdutycycle, [:uint], :int
|
10
|
+
|
11
|
+
# Args: gpio, range (25-40000)
|
12
|
+
attach_function :gpioSetPWMrange, [:uint, :uint], :int
|
13
|
+
|
14
|
+
# Args: gpio
|
15
|
+
attach_function :gpioGetPWMrange, [:uint], :int
|
16
|
+
|
17
|
+
# Args: gpio
|
18
|
+
attach_function :gpioGetPWMrealRange, [:uint], :int
|
19
|
+
|
20
|
+
# Args: gpio, frequency (In Hz, matches nearest available. See pigpio docs for more)
|
21
|
+
attach_function :gpioSetPWMfrequency, [:uint, :uint], :int
|
22
|
+
|
23
|
+
# Args: gpio
|
24
|
+
attach_function :gpioGetPWMfrequency, [:uint], :int
|
25
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module PiGPIO
|
2
|
+
extend FFI::Library
|
3
|
+
ffi_lib 'pigpio'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Open a handle for SPI device on the bus
|
7
|
+
#
|
8
|
+
# Args: spiChan, baud, spiFlags (see pigpio docs)
|
9
|
+
# spiFlags control mode, chip select, LSB/MSB etc.
|
10
|
+
#
|
11
|
+
# Returns: handle as integer
|
12
|
+
attach_function :spiOpen, [:uint, :uint32, :uint32], :int
|
13
|
+
|
14
|
+
#
|
15
|
+
# Close an SPI device handle.
|
16
|
+
#
|
17
|
+
# Args: handle
|
18
|
+
attach_function :i2cClose, [:uint], :int
|
19
|
+
|
20
|
+
#
|
21
|
+
# Read length bytes from the given SPI handle.
|
22
|
+
#
|
23
|
+
# Don't call this directly.
|
24
|
+
# Args: handle, buffer, count
|
25
|
+
attach_function :_spiRead, :spiRead, [:uint, :pointer, :uint], :int
|
26
|
+
#
|
27
|
+
# Call this instead.
|
28
|
+
def self.spiRead(handle, length)
|
29
|
+
# Limited to word sizes of 8 bits.
|
30
|
+
buffer_pointer = FFI::MemoryPointer.new(:uint8, length)
|
31
|
+
|
32
|
+
# Read it and convert it to a Ruby array.
|
33
|
+
self._spiRead(handle, buffer_pointer, length)
|
34
|
+
bytes = buffer_pointer.read_array_of_type(:uint8, length)
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Write bytes to the given SPI handle.
|
39
|
+
#
|
40
|
+
# Don't call this directly.
|
41
|
+
attach_function :_spiWrite, :spiWrite, [:uint, :pointer, :uint], :int
|
42
|
+
#
|
43
|
+
# Call this instead.
|
44
|
+
def self.spiWrite(handle, byte_array)
|
45
|
+
# Do some validation.
|
46
|
+
byte_array.each do |element|
|
47
|
+
raise ArgumentError, "Byte values must be within 0x00 and 0xFF" if (element > 0xFF || element < 0x00)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Copy the array to the pointer location.
|
51
|
+
buffer_pointer = FFI::MemoryPointer.new(:uint8, byte_array.length)
|
52
|
+
buffer_pointer.write_array_of_type(:uint8, byte_array)
|
53
|
+
|
54
|
+
# Write it.
|
55
|
+
self._spiWrite(handle, buffer_pointer, buffer_pointer.length)
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Xfer bytes from the SPI handle. Reads as many bytes as the legnth of the tx_buffer.
|
60
|
+
#
|
61
|
+
# Don't call this directly.
|
62
|
+
attach_function :_spiXfer, :spiXfer, [:uint, :pointer, :pointer, :uint], :int
|
63
|
+
#
|
64
|
+
# Call this instead.
|
65
|
+
def self.spiXfer(handle, tx_array)
|
66
|
+
tx_array.each do |element|
|
67
|
+
raise ArgumentError, "Byte values must be within 0x00 and 0xFF" if (element > 0xFF || element < 0x00)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Copy the tx array to the pointer location.
|
71
|
+
tx_pointer = FFI::MemoryPointer.new(:uint8, tx_array.length)
|
72
|
+
tx_pointer.write_array_of_type(:uint8, tx_array)
|
73
|
+
|
74
|
+
# Make pointer for the receive buffer.
|
75
|
+
rx_pointer = FFI::MemoryPointer.new(:uint8, tx_array.length)
|
76
|
+
|
77
|
+
# Transfer.
|
78
|
+
self._spiWrite(handle, buffer_pointer, buffer_pointer.length)
|
79
|
+
|
80
|
+
# Read bytes from the rx pointer.
|
81
|
+
rx_bytes = rx_pointer.read_array_of_type(:uint8, tx_array.length)
|
82
|
+
end
|
83
|
+
|
84
|
+
# bbSPIOpen not mapped.
|
85
|
+
# bbSPIClose not mapped.
|
86
|
+
# bbSPIXfer not mapped.
|
87
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module PiGPIO
|
2
|
+
extend FFI::Library
|
3
|
+
ffi_lib 'pigpio'
|
4
|
+
|
5
|
+
# Args: delay time in microseconds
|
6
|
+
# Returns: actual delay time in microseconds
|
7
|
+
attach_function :gpioDelay, [:uint32], :uint32
|
8
|
+
|
9
|
+
#
|
10
|
+
# Returns: current system tick (microseconds with 72 miniute rollover)
|
11
|
+
attach_function :gpioTick, [], :uint32
|
12
|
+
|
13
|
+
# Returns: integer corresponding to Raspberry Pi hardware revision
|
14
|
+
attach_function :gpioHardwareRevision, [], :uint
|
15
|
+
|
16
|
+
# Returns: pigpio version
|
17
|
+
attach_function :gpioVersion, [], :uint
|
18
|
+
|
19
|
+
# getBitInBytes not mapped.
|
20
|
+
# putBitInBytes not mapped.
|
21
|
+
# gpioTime not mapped.
|
22
|
+
# gpioSleep not mapped.
|
23
|
+
# time_time not mapped.
|
24
|
+
# time_sleep not mapped.
|
25
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module PiGPIO
|
2
|
+
extend FFI::Library
|
3
|
+
ffi_lib 'pigpio'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Struct for holding a single pulse. Given as a hash in Ruby.
|
7
|
+
# gpioOn and gpioOff are bitmasks 32 bits long, NOT GPIO numbers.
|
8
|
+
class WavePulse < FFI::Struct
|
9
|
+
layout :gpioOn, :uint32,
|
10
|
+
:gpioOff, :uint32,
|
11
|
+
:usDelay, :uint32
|
12
|
+
end
|
13
|
+
|
14
|
+
attach_function :gpioWaveClear, [], :int
|
15
|
+
attach_function :gpioWaveAddNew, [], :int
|
16
|
+
|
17
|
+
#
|
18
|
+
# Don't call this directly.
|
19
|
+
attach_function :_gpioWaveAddGeneric, :gpioWaveAddGeneric, [:uint, :pointer], :int
|
20
|
+
#
|
21
|
+
# Call this instead. No length arg like C function.
|
22
|
+
# Args: array of pulse hashes.
|
23
|
+
def self.gpioWaveAddGeneric(pulses=[])
|
24
|
+
pulses_pointer = FFI::MemoryPointer.new(WavePulse, pulses.length)
|
25
|
+
pulse_structs = pulses.length.times.collect do |i|
|
26
|
+
WavePulse.new(pulses_pointer + i * WavePulse.size)
|
27
|
+
end
|
28
|
+
pulses.each_with_index do |hash, i|
|
29
|
+
pulse_structs[i][:gpioOn] = hash[:gpioOn]
|
30
|
+
pulse_structs[i][:gpioOff] = hash[:gpioOff]
|
31
|
+
pulse_structs[i][:usDelay] = hash[:usDelay]
|
32
|
+
end
|
33
|
+
self._gpioWaveAddGeneric(pulses.length, pulses_pointer)
|
34
|
+
end
|
35
|
+
|
36
|
+
# gpioWaveAddSerial not mapped.
|
37
|
+
|
38
|
+
# Returns: wave_id
|
39
|
+
attach_function :gpioWaveCreate, [], :int
|
40
|
+
|
41
|
+
# gpioWaveCreatePad not mapped.
|
42
|
+
|
43
|
+
# Args: wave_id
|
44
|
+
attach_function :gpioWaveDelete, [:uint], :int
|
45
|
+
|
46
|
+
# Args: wave_id, mode (0 = oneshot, 1 = repeat, 2 = oneshot sync, 3 = repeat sync)
|
47
|
+
attach_function :gpioWaveTxSend, [:uint, :uint], :int
|
48
|
+
|
49
|
+
#
|
50
|
+
# Don't call this directly.
|
51
|
+
attach_function :_gpioWaveChain, :gpioWaveChain, [:pointer, :uint], :int
|
52
|
+
#
|
53
|
+
# Call this instead. No length arg like C function.
|
54
|
+
# Args: array of wave_ids to send in order.
|
55
|
+
def self.gpioWaveChain(wave_id_array=[])
|
56
|
+
# NOTE: Should add validation here? Each array element should be a byte.
|
57
|
+
# Maximum number of bytes should be 600.
|
58
|
+
|
59
|
+
# Just pack the byte array into a string. Gets mapped to char * in C.
|
60
|
+
string = wave_id_array.pack('C*')
|
61
|
+
self._gpioWaveChain(string, wave_id_array.length)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns: wave_id of wave being transmitted
|
65
|
+
attach_function :gpioWaveTxAt, [], :int
|
66
|
+
|
67
|
+
# Returns: 1 if transmitting, 0 otherwise
|
68
|
+
attach_function :gpioWaveTxBusy, [], :int
|
69
|
+
|
70
|
+
# Returns: 0 if OK
|
71
|
+
attach_function :gpioWaveTxStop, [], :int
|
72
|
+
|
73
|
+
# Returns: length (in microseconds) of current wave
|
74
|
+
attach_function :gpioWaveGetMicros, [], :int
|
75
|
+
|
76
|
+
# Returns: length of longest wave since initialise (in terms of microseconds)
|
77
|
+
attach_function :gpioWaveGetHighMicros, [], :int
|
78
|
+
|
79
|
+
# Returns: length of longest wave possible (in terms of microseconds)
|
80
|
+
attach_function :gpioWaveGetMaxMicros, [], :int
|
81
|
+
|
82
|
+
# Returns: length (in pulses) of current wave
|
83
|
+
attach_function :gpioWaveGetPulses, [], :int
|
84
|
+
|
85
|
+
# Returns: length of longest wave since initialise (in terms of pulses)
|
86
|
+
attach_function :gpioWaveGetHighPulses, [], :int
|
87
|
+
|
88
|
+
# Returns: length of longest wave possible (in terms of pulses)
|
89
|
+
attach_function :gpioWaveGetMaxPulses, [], :int
|
90
|
+
|
91
|
+
# Returns: length of longest wave since initialise (in terms of DMA control blocks)
|
92
|
+
attach_function :gpioWaveGetCbs, [], :int
|
93
|
+
|
94
|
+
# Returns: length of longest wave possible (in terms of DMA control blocks)
|
95
|
+
attach_function :gpioWaveGetHighCbs, [], :int
|
96
|
+
|
97
|
+
# Returns: length of longest wave possible (in terms of DMA control blocks)
|
98
|
+
attach_function :gpioWaveGetMaxCbs, [], :int
|
99
|
+
end
|
data/lib/pigpio_ffi.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Each file adds methods to the PiGPIO module, corresponding to a named
|
5
|
+
# section of the pigpgio C interface docs, located here:
|
6
|
+
# https://abyz.me.uk/rpi/pigpio/cif.html
|
7
|
+
#
|
8
|
+
# NOTE: nothing from the following sections is mapped:
|
9
|
+
# Custom, Events, Files, Scripts, Serial, I2C/SPI Slave, Expert
|
10
|
+
#
|
11
|
+
require_relative 'pigpio_ffi/version'
|
12
|
+
require_relative 'pigpio_ffi/essential'
|
13
|
+
require_relative 'pigpio_ffi/basic'
|
14
|
+
require_relative 'pigpio_ffi/pwm'
|
15
|
+
require_relative 'pigpio_ffi/servo'
|
16
|
+
require_relative 'pigpio_ffi/intermediate'
|
17
|
+
require_relative 'pigpio_ffi/advanced'
|
18
|
+
require_relative 'pigpio_ffi/i2c'
|
19
|
+
require_relative 'pigpio_ffi/spi'
|
20
|
+
require_relative 'pigpio_ffi/waves'
|
21
|
+
require_relative 'pigpio_ffi/utilities'
|
22
|
+
require_relative 'pigpio_ffi/configuration'
|
23
|
+
|
24
|
+
#
|
25
|
+
# Additional convenience and helper methods added here.
|
26
|
+
#
|
27
|
+
module PiGPIO
|
28
|
+
extend FFI::Library
|
29
|
+
ffi_lib 'pigpio'
|
30
|
+
|
31
|
+
# Helper to handle systick integer rollover calculation.
|
32
|
+
def self.gpioTicksSince(old_time)
|
33
|
+
current_time = gpioTick
|
34
|
+
if current_time < old_time
|
35
|
+
(0xFFFF - old_time) + current_time
|
36
|
+
else
|
37
|
+
current_time - old_time
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/pigpio_ffi.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative 'lib/pigpio_ffi/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'pigpio_ffi'
|
5
|
+
s.version = PiGPIO::VERSION
|
6
|
+
s.licenses = ['MIT']
|
7
|
+
s.summary = "FFI bindings for pigpio C library on Raspberry Pi devices"
|
8
|
+
s.description = "Use your Raspberry Pi GPIO pins in Ruby. This gem uses FFI to provide Ruby bindings for the pigpio C library on compatible Raspberry Pi Devices."
|
9
|
+
s.authors = ["vickash"]
|
10
|
+
s.email = 'vickashmahabir@gmail.com'
|
11
|
+
s.files = Dir['**/*']
|
12
|
+
s.homepage = 'https://github.com/dino-rb/pigpio_ffi'
|
13
|
+
s.metadata = { "source_code_uri" => "https://github.com/dino-rb/pigpio_ffi" }
|
14
|
+
|
15
|
+
s.add_dependency 'ffi'
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pigpio_ffi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- vickash
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-03-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi
|
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: Use your Raspberry Pi GPIO pins in Ruby. This gem uses FFI to provide
|
28
|
+
Ruby bindings for the pigpio C library on compatible Raspberry Pi Devices.
|
29
|
+
email: vickashmahabir@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- LICENSE
|
35
|
+
- README.md
|
36
|
+
- lib/pigpio_ffi.rb
|
37
|
+
- lib/pigpio_ffi/advanced.rb
|
38
|
+
- lib/pigpio_ffi/basic.rb
|
39
|
+
- lib/pigpio_ffi/configuration.rb
|
40
|
+
- lib/pigpio_ffi/essential.rb
|
41
|
+
- lib/pigpio_ffi/i2c.rb
|
42
|
+
- lib/pigpio_ffi/intermediate.rb
|
43
|
+
- lib/pigpio_ffi/pwm.rb
|
44
|
+
- lib/pigpio_ffi/servo.rb
|
45
|
+
- lib/pigpio_ffi/spi.rb
|
46
|
+
- lib/pigpio_ffi/utilities.rb
|
47
|
+
- lib/pigpio_ffi/version.rb
|
48
|
+
- lib/pigpio_ffi/waves.rb
|
49
|
+
- pigpio_ffi.gemspec
|
50
|
+
homepage: https://github.com/dino-rb/pigpio_ffi
|
51
|
+
licenses:
|
52
|
+
- MIT
|
53
|
+
metadata:
|
54
|
+
source_code_uri: https://github.com/dino-rb/pigpio_ffi
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubygems_version: 3.4.8
|
71
|
+
signing_key:
|
72
|
+
specification_version: 4
|
73
|
+
summary: FFI bindings for pigpio C library on Raspberry Pi devices
|
74
|
+
test_files: []
|