A Common Lisp interface to the Rapsberry Pi pigpio library (pigpio on github)
pigpio is a library to provide a simplified interface to the Raspberry Pi's hardware devices, like SPI, I2C, Serial, and GPIO.
pigpio has 1) a direct hardware version (linking with libpigpio.so) that requires the program using it to run as root; and 2) a pigpiod daemon (linked with libpigpiod_if2.so) that allows user-land programs to accesss hardware via network calls to the daemon.
CL-PIGPIO links with both libraries, and allows the user to select whether the hardware or the daemon form is called. If the hardware version is activated but the user's program is not running with root privileges, an error is generated.
Only one of the two (hardware or daemon) can be run on the same RPi, but the daemon on other RPis can be accessed remotely.
Install in your usual Lisp package tree and run
(asdf:load-system "cl-pigpio")
or, for just the low level FFI, run
(asdf:load-system "pigpio-ffi-universal")
The unified pigpio/pigpiod interface is in the pigpio-ffi-universal package.
Here, the routines are generally the same as documented in the C pigpio interface but with an additional keyword device specifier.
For example, if the C library has
int i2cOpen(unsigned i2cBus, unsigned i2cAddr, unsigned i2cFlags);
then the Lisp version has
(pigpio-ffi-universal:pigpio-i2copen
i2cbus i2caddr i2cflags
&key (pidev pigpio-ffi-unversal:*default-pidev*))
The pidev keyword argument can be set as
;; daemon form, setting *default-pidev* to this device
(pigpio-ffi-universal:open-pidev/daemon :host "localhost" :port "8888"
:set-default t)
;; OR open hardware device, this time not setting the default variable
(defparameter *my-pidev*
(pigpio-ffi-universal:open-pidev/hardware :set-default nil))
It is necessary to open a device before making any pigpio/pigpiod calls.
The cl-pigpio package contains a higher level interface to SPI, I2C, and GPIO.
This interface is not documented in detail, but the exported functions are visible in cl-pigpio-package.lisp, and the functions generally have good documentation strings. I2C, SPI, and GPIO have separate source files.
The purpose of the higher level interface is to translate opaque data like I2C flags into more easily understable Lisp keywords, and to perform FFI calls using Lisp buffers rather than using CFFI foreign pointers.
The high level routines also throw a descriptive Lisp error if the pigpio library returns an error.
- pigpio does not work for RPi5 (yet?) because hardware interface is not documented
- signals are turned off in the hardware version using
gpioCfgGetInternals()
to prevent clashes with any Lisp use of signals.
Tested with 64 bit SBCL, on Bookworm.