Swift bindings for the rpi_ws281x library.
This package has two libraries. rpi_ws281x_swift
provides a user-friendly Swifty interface, with native classes and enums. rpi_ws281x
simply bridges the rpi_ws281x C headers into Swift.
The README for rpi_ws281x is recommended reading. It contains useful background information about using a Raspberry Pi to control an LED strip.
The demo program uses DMA on channel 10 to run PWM on GPIO 18, which corresponds to pin 12 on the Raspberry Pi's GPIO header. It must be run with sudo
as it requires direct memory access.
git clone https://github.com/kbongort/rpi-ws281x-swift
cd rpi-ws281x-swift
swift build
sudo .build/debug/Demo
Add this library as a dependency to your target:
// swift-tools-version: 5.4
import PackageDescription
let package = Package(
name: "YourPackageName",
dependencies: [
.package(url: "https://github.com/kbongort/rpi-ws281x-swift.git", from: "2.0.0"),
],
targets: [
.target(
name: "YourTargetName",
dependencies: [
.product(name: "rpi_ws281x_swift", package: "rpi-ws281x-swift"),
])
]
)
The library has three classes for controlling LED strips to serve use cases from basic to advanced. LedStrip
is a user-friendly class for controlling a single strip of LEDs. DualPwmLedStrip
is a specialized class for controlling two strips of LEDs with PWM on two channels. Both inherit from Ws2811
, which is a lightweight wrapper for the C API.
This library endeavors to provide simple, well-lit paths to working LEDs. It also provides the ability to "break glass" and use less common configurations.
For developer convenience, this library can be compiled and run on Mac, but it will only make calls to the underlying C library on Linux.
Most use cases should be well served by LedStrip
. It is initialized with a channel using a
GPIO number corresponding to one of the available output methods (SPI, PWM, or PCM).
Use it as follows:
import rpi_ws281x_swift
let ledStrip = try! LedStrip(Channel(gpio: .gpio18, ledCount: 10, stripType: .ws2811_GRB))
// Set LED colors
let colors = Array(repeating: 0x00FF0000 /* red */, count: 10)
try! ledStrip.render(colors)
// Later…
ledString.finish()
See main.swift for a complete example.
The DualPwmLedStrip
class can control two LED strips with dual-channel
PWM. Usage is similar to LedStrip, but with two channels instead of one. Channels use GPIO numbers compatible with PWM on channels 0 and 1, respectively.
import rpi_ws281x_swift
let ledStrip = try! LedStrip(Channel(gpio: .gpio18, ledCount: 10, stripType: .ws2811_GRB),
Channel(gpio: .gpio13, ledCount: 10, stripType: .ws2811_GRB))
// Set LED colors
let channel0Colors = Array(repeating: 0x00FF0000 /* red */, count: 10)
let channel1Colors = Array(repeating: 0x0000FF00 /* green */, count: 10)
try! ledStrip.render(channel0Colors, channel1Colors)
// Later…
ledString.finish()
A lightweight wrapper around ws2811_t
, and the base class for LedStrip
and DualPwmLedStrip
. Can be initialized with one or two channels, and any GPIO numbers (not all are valid, and validity is hardware-dependant – the underlying rpi_ws281x library will check).
There are two options for rendering with this class. The renderWithCallback()
method takes a callback that should write color values to buffers passed in its arguments. Alternatively, one may write directly to the arrays in ws2811.channels.0.leds
and ws2811.channels.1.leds
, and call render()
.
import rpi_ws281x_swift
let ledStrip = try! Ws2811(channel0: Channel(gpio: 18, ledCount: 10, stripType: .ws2811_GRB))
for i in 0..<10 {
ledStrip.ws2811.channel.0.leds[i] = 0x00FF0000 // red
}
try! ledStrip.render();
The Channel
struct holds configuration data for a single channel. It wraps a ws2811_channel_t
struct, and provides direct access to that struct for advanced configuration via the ws2811Channel
property.
var channel = Channel(gpio: LedStrip.Gpio.gpio18, ledCount: 10, stripType: .ws2811_GRB)
channel.ws2811Channel.brightness = 127 // 50% brightness
PackedColor
is a type alias for UInt32
, and provides helper methods for packing UInt8 and Float color values into WRGB UInt32s as required for rendering with this library.
let red = PackedColor.fromRgb(1.0, 0.0, 0.0)
Most of the functions in the rpi_ws281x library return status codes to indicate success or an error. As Swift typically uses exceptions for error handling, this library wraps and throws error status as the Ws291xError
struct. Ws291xError
provides access to the underlying error code, and its localizedDescription
property returns a description generated by the rpi_ws281x library.
The rpi_ws281x
library is a simple bridge for the C library. For usage, please refer to the documentation for that library.
So that programs using this library can be built and run on Macs, the rpi_ws281x wrapper library compiles its sources only on Linux. On Mac, its headers are available but functions cannot be called as there is nothing to link to. In cross-platform code, function calls should be wrapped in #if os(Linux)
directives:
import rpi_ws281x
var ws2811 = ws2811_t()
#if os(Linux)
let ret = ws2811_init(&ws2811)
#endif