pigpio_ffi 0.1.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 +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: []
|