• Stars
    star
    181
  • Rank 212,110 (Top 5 %)
  • Language
    C
  • License
    MIT License
  • Created over 10 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Lua library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux.

lua-periphery Build Status GitHub release License

Linux Peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) with Lua

lua-periphery is a library for GPIO, LED, PWM, SPI, I2C, MMIO, and Serial peripheral I/O interface access in userspace Linux. It is useful in embedded Linux environments (including Raspberry Pi, BeagleBone, etc. platforms) for interfacing with external peripherals. lua-periphery is compatible with Lua 5.1 (including LuaJIT), Lua 5.2, Lua 5.3, and Lua 5.4, has no dependencies outside the standard C library and Linux, is portable across architectures, and is MIT licensed.

Using Python or C? Check out the python-periphery and c-periphery projects.

Contributed libraries: java-periphery, dart_periphery

Examples

GPIO

local GPIO = require('periphery').GPIO

-- Open GPIO /dev/gpiochip0 line 10 with input direction
local gpio_in = GPIO("/dev/gpiochip0", 10, "in")
-- Open GPIO /dev/gpiochip0 line 12 with output direction
local gpio_out = GPIO("/dev/gpiochip0", 12, "out")

local value = gpio_in:read()
gpio_out:write(not value)

gpio_in:close()
gpio_out:close()

Go to GPIO documentation.

LED

local LED = require('periphery').LED

-- Open LED led0
local led = LED("led0")

-- Turn on LED (set max brightness)
led:write(true)

-- Set half brightness
led:write(math.floor(led.max_brightness / 2))

-- Turn off LED (set zero brightness)
led:write(false)

led:close()

Go to LED documentation.

PWM

local PWM = require('periphery').PWM

-- Open PWM chip 0, channel 10
local pwm = PWM(0, 10)

-- Set frequency to 1 kHz
pwm.frequency = 1e3
-- Set duty cycle to 75%
pwm.duty_cycle = 0.75

-- Enable PWM output
pwm:enable()

pwm:close()

Go to PWM documentation.

SPI

local SPI = require('periphery').SPI

-- Open spidev1.0 with mode 0 and max speed 1MHz
local spi = SPI("/dev/spidev1.0", 0, 1e6)

local data_out = {0xaa, 0xbb, 0xcc, 0xdd}
local data_in = spi:transfer(data_out)

print(string.format("shifted out {0x%02x, 0x%02x, 0x%02x, 0x%02x}", unpack(data_out)))
print(string.format("shifted in  {0x%02x, 0x%02x, 0x%02x, 0x%02x}", unpack(data_in)))

spi:close()

Go to SPI documentation.

I2C

local I2C = require('periphery').I2C

-- Open i2c-0 controller
local i2c = I2C("/dev/i2c-0")

-- Read byte at address 0x100 of EEPROM at 0x50
local msgs = { {0x01, 0x00}, {0x00, flags = I2C.I2C_M_RD} }
i2c:transfer(0x50, msgs)
print(string.format("0x100: 0x%02x", msgs[2][1]))

i2c:close()

Go to I2C documentation.

MMIO

local MMIO = require('periphery').MMIO

-- Open am335x real-time clock subsystem page
local rtc_mmio = MMIO(0x44E3E000, 0x1000)

-- Read current time
local rtc_secs = rtc_mmio:read32(0x00)
local rtc_mins = rtc_mmio:read32(0x04)
local rtc_hrs = rtc_mmio:read32(0x08)

print(string.format("hours: %02x minutes: %02x seconds: %02x", rtc_hrs, rtc_mins, rtc_secs))

rtc_mmio:close()

-- Open am335x control module page
local ctrl_mmio = MMIO(0x44E10000, 0x1000)

-- Read MAC address
local mac_id0_lo = ctrl_mmio:read32(0x630)
local mac_id0_hi = ctrl_mmio:read32(0x634)

print(string.format("MAC address: %04x%08x", mac_id0_lo, mac_id0_hi))

ctrl_mmio:close()

Go to MMIO documentation.

Serial

local Serial = require('periphery').Serial

-- Open /dev/ttyUSB0 with baudrate 115200, and defaults of 8N1, no flow control
local serial = Serial("/dev/ttyUSB0", 115200)

serial:write("Hello World!")

-- Read up to 128 bytes with 500ms timeout
local buf = serial:read(128, 500)
print(string.format("read %d bytes: _%s_", #buf, buf))

serial:close()

Go to Serial documentation.

Error Handling

lua-periphery errors are descriptive table objects with an error code string, C errno, and a user message.

-- Example of error caught with pcall()
> status, err = pcall(function () spi = periphery.SPI("/dev/spidev1.0", 0, 1e6) end)
> =status
false
> dump(err)
{
  message = "Opening SPI device \"/dev/spidev1.0\": Permission denied [errno 13]",
  c_errno = 13,
  code = "SPI_ERROR_OPEN"
}
> 

-- Example of error propagated to user
> periphery = require('periphery')
> spi = periphery.SPI('/dev/spidev1.0', 0, 1e6)
Opening SPI device "/dev/spidev1.0": Permission denied [errno 13]
> 

Note about Lua 5.1

Lua 5.1 does not automatically render the string representation of error objects that are reported to the console, and instead shows the following error message:

> periphery = require('periphery')
> gpio = periphery.GPIO(14, 'in')
(error object is not a string)
> 

These errors can be caught with pcall() and rendered in their string representation with tostring(), print(), or by evaluation in the interactive console:

> periphery = require('periphery')
> gpio, err = pcall(periphery.GPIO, 14, 'in')
> =tostring(err)
Opening GPIO: opening 'export': Permission denied [errno 13]
> print(err)
Opening GPIO: opening 'export': Permission denied [errno 13]
> =err
Opening GPIO: opening 'export': Permission denied [errno 13]
> 

This only applies to Lua 5.1. LuaJIT and Lua 5.2 onwards automatically render the string representation of error objects that are reported to the console.

Documentation

man page style documentation for each interface is available in docs folder.

Installation

Build and install with LuaRocks

$ sudo luarocks install lua-periphery

Build and install from source

Clone lua-periphery recursively to also fetch c-periphery, which lua-periphery is built on.

$ git clone --recursive https://github.com/vsergeev/lua-periphery.git
$ cd lua-periphery
$ make clean all
$ cp periphery.so /path/to/lua/libs/

Place periphery.so in a directory searched by the Lua package.cpath variable. For example: /usr/lib/lua/5.3/, the same directory as other Lua sources, etc.

lua-periphery can then be loaded in lua with periphery = require('periphery').

Cross-compiling from Source

Set the CROSS_COMPILE environment variable with the cross-compiler prefix when calling make. Your target's sysroot must provide the Lua includes.

$ CROSS=arm-linux- make clean all
cd c-periphery && make clean
make[1]: Entering directory '/home/anteater/projects/software/lua-periphery/c-periphery'
rm -rf periphery.a obj tests/test_serial tests/test_i2c tests/test_gpio_sysfs tests/test_mmio tests/test_spi tests/test_gpio
make[1]: Leaving directory '/home/anteater/projects/software/lua-periphery/c-periphery'
rm -rf periphery.so
cd c-periphery; make
make[1]: Entering directory '/home/anteater/projects/software/lua-periphery/c-periphery'
mkdir obj
arm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter  -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\"  -c src/gpio.c -o obj/gpio.o
arm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter  -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\"  -c src/spi.c -o obj/spi.o
arm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter  -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\"  -c src/i2c.c -o obj/i2c.o
arm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter  -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\"  -c src/mmio.c -o obj/mmio.o
arm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter  -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\"  -c src/serial.c -o obj/serial.o
arm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter  -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\"  -c src/version.c -o obj/version.o
arm-linux-ar rcs periphery.a obj/gpio.o obj/spi.o obj/i2c.o obj/mmio.o obj/serial.o obj/version.o
make[1]: Leaving directory '/home/anteater/projects/software/lua-periphery/c-periphery'
arm-linux-gcc  -std=c99 -pedantic -D_XOPEN_SOURCE=700 -Wall -Wextra -Wno-unused-parameter  -fPIC -I.  -Iinc  -shared src/lua_periphery.c src/lua_mmio.c src/lua_
gpio.c src/lua_spi.c src/lua_i2c.c src/lua_serial.c c-periphery/periphery.a -o periphery.so
$ file periphery.so
periphery.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, not stripped
$

Testing

The tests located in the tests folder may be run under Lua to test the correctness and functionality of lua-periphery. Some tests require interactive probing (e.g. with an oscilloscope), the installation of a physical loopback, or the existence of a particular device on a bus. See the usage of each test for more details on the required setup.

License

lua-periphery is MIT licensed. See the included LICENSE file.

More Repositories

1

c-periphery

A C library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux.
C
727
star
2

luaradio

A lightweight, embeddable software-defined radio framework built on LuaJIT
Lua
604
star
3

python-periphery

A pure Python 2/3 library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux.
Python
529
star
4

u-msgpack-python

A portable, lightweight MessagePack serializer and deserializer written in pure Python, compatible with Python 2, Python 3, CPython, PyPy / msgpack.org[Python]
Python
253
star
5

briefsky

A free weather frontend to a variety of weather providers
TypeScript
243
star
6

apfcp

x86 Assembly Primer for C Programmers
Assembly
211
star
7

btckeygenie

A standalone Bitcoin keypair/address generator, written in Go.
Go
104
star
8

ntgbtminer

A no thrills getblocktemplate Bitcoin miner, written in Python.
Python
83
star
9

vavrdisasm

vAVRdisasm is an 8-bit Atmel AVR disassembler.
C
74
star
10

audioprism

A spectrogram tool for PulseAudio and WAV files, written in C++11.
C++
63
star
11

tinytaptunnel

a point-to-point layer 2 tap interface tunnel over UDP/IP with HMAC-SHA256 authentication, written in Go.
Go
57
star
12

ssterm

A simple console-based serial port terminal, written in Python.
Python
52
star
13

libGIS

libGIS is a collection of utility functions to create, read and write Atmel Generic, Intel HEX8, and Motorola S-Record formatted files.
C
50
star
14

0xtrades.info

A real-time trade viewer for the 0x protocol.
TypeScript
36
star
15

snake.ts

A simple snake implementation in TypeScript and blessed.
TypeScript
22
star
16

3d-gears

3D Parametric Gears made with Fusion 360
18
star
17

arm-bmw-sw

ARM Bare Metal Widget (arm-bmw) software
C
18
star
18

mbed-cmsis

Building your own CMSIS Code for the mbed.
C
17
star
19

vpicdisasm

vPICdisasm is a Microchip PIC disassembler for Baseline, Mid-Range, and Mid-Range Enhanced 8-bit PIC cores.
C
16
star
20

arm-bmw-hw

ARM Bare Metal Widget (arm-bmw) hardware
Eagle
15
star
21

cmsis-templates

CMSIS v3.20 Bootstrapping Templates for GNU ARM Tools
C
14
star
22

v8cpu

v8cpu is a simple multi-cycle von Neumann architecture 8-bit CPU in under 500 lines of Verilog.
Verilog
14
star
23

teatimer

A simple kitchen timer implemented in digital logic on a Lattice MachXO2 CPLD.
Eagle
14
star
24

gardend-lua

A modular, discrete-time control daemon for a hydroponic garden, written in Lua.
Lua
12
star
25

radio-decoders

Python
11
star
26

evolve110

Rule 110 on the Ethereum blockchain
JavaScript
9
star
27

libGISdotnet

libGIS ported to .NET.
C#
8
star
28

wireless-triac

Wireless ZigBee/XBee Controlled TRIAC (Sep 2009)
C
8
star
29

zigradio

A lightweight software-defined radio framework built with Zig
Zig
7
star
30

rigexpert-tool

Dump, plot, and convert impedance sweeps from a RigExpert antenna analyzer.
Python
6
star
31

qrd

Simple QR Code decoder for educational purposes
Python
6
star
32

minifortune

A minimal fortune-mod clone, written in C.
C
6
star
33

basic-makefiles

TeX
6
star
34

3d-simple-iso-thread

A simple, single-file modeled ISO thread module for OpenSCAD
OpenSCAD
4
star
35

3d-holster-claw

A 3D printable holster claw accessory made with Fusion 360
3
star
36

wireless-power-meter

Wireless ZigBee/XBee V-I Power Meter (Sep 2009)
Python
2
star
37

3d-mini-turntable

A miniature motorized turntable for small objects made with OpenSCAD
OpenSCAD
2
star
38

3d-fiber-enclosure

A 3D printable fiber optic project enclosure made with Fusion 360
1
star
39

3d-webcam-mount

3D Printable Webcam Mount made with Fusion 360
1
star
40

3d-jewelry-box

A 3D printable jewelry box made with OpenSCAD
OpenSCAD
1
star
41

3d-flosser-holder

A 3D printable flosser holder made with OpenSCAD
OpenSCAD
1
star
42

template110

Rule 110 implemented with C++11 templates and std::array.
C++
1
star
43

wclock

LED Word Clock (Mar 2012)
Eagle
1
star
44

yatumblr-backup

yet another tumblr backup script
Python
1
star