lgpio(3)
๐ lgpio โ the C library that talks to your SBC's GPIO ๐
okay bestie, welcome to lgpio(3), straight outta the lg archive โจ this is the whole vibe: a C library that lets you control the General Purpose Input Output pins on a Linux Single Board Computer. she's long, she's iconic, and she's about to be your whole personality. let's go ๐
๐ธ NAME ๐ธ
lgpio โ a C library to manipulate a local SBC's GPIO. yes. that's the whole job. and she ate. ๐ซถ
โจ SYNOPSIS โจ
#include <lgpio.h>
gcc -Wall -o prog prog.c -llgpio
./prog
like, that's it. that's the ritual. ๐
๐ฆ DESCRIPTION ๐ฆ
lgpio is a C library for Linux Single Board Computers which allows control of the General Purpose Input Output pins. that's the mission statement, and she is so committed to it. ๐
๐ Features
- reading and writing GPIO singly and in groups
- software timed PWM and waves
- GPIO callbacks
- pipe notification of GPIO alerts
- I2C wrapper
- SPI wrapper
- serial link wrapper
- a simple interface to start and stop new threads
look at that list. every single one. no skips, no cuts, we love a full feature set fr fr ๐
๐ง Usage
Include <lgpio.h> in your source files.
Assuming your source is in a single file called prog.c use the following command to build and run the executable.
gcc -Wall -o prog prog.c -llgpio
For examples of usage see the C programs within the lg archive file. ๐
๐ Notes
All the functions which return an int return < 0 on error.
ok so this is THE rule to internalise: if an int comes back negative, something went wrong. that's your vibe check, always. ๐ญ
๐ OVERVIEW ๐
โญ GPIO
lgGpiochipOpenโ Opens a gpiochip devicelgGpiochipCloseโ Closes a gpiochip devicelgGpioGetChipInfoโ Gets gpiochip informationlgGpioGetLineInfoโ Gets gpiochip line informationlgGpioGetModeโ Gets the mode of a GPIOlgGpioSetUserโ Notifies Linux of the GPIO userlgGpioClaimInputโ Claims a GPIO for inputlgGpioClaimOutputโ Claims a GPIO for outputlgGpioClaimAlertโ Claims a GPIO for alertslgGpioFreeโ Frees a GPIOlgGroupClaimInputโ Claims a group of GPIO for inputslgGroupClaimOutputโ Claims a group of GPIO for outputslgGroupFreeโ Frees a group of GPIOlgGpioReadโ Reads a GPIOlgGpioWriteโ Writes a GPIOlgGroupReadโ Reads a group of GPIOlgGroupWriteโ Writes a group of GPIOlgTxPulseโ Starts pulses on a GPIOlgTxPwmโ Starts PWM pulses on a GPIOlgTxServoโ Starts Servo pulses on a GPIOlgTxWaveโ Starts a wave on a group of GPIOlgTxBusyโ See if tx is active on a GPIO or grouplgTxRoomโ See if more room for tx on a GPIO or grouplgGpioSetDebounceโ Sets the debounce time for a GPIOlgGpioSetWatchdogโ Sets the watchdog time for a GPIOlgGpioSetAlertsFuncโ Starts a GPIO callbacklgGpioSetSamplesFuncโ Starts a GPIO callback for all GPIO
๐ฅ I2C
lgI2cOpenโ Opens an I2C devicelgI2cCloseโ Closes an I2C devicelgI2cWriteQuickโ SMBus write quicklgI2cReadByteโ SMBus read bytelgI2cWriteByteโ SMBus write bytelgI2cReadByteDataโ SMBus read byte datalgI2cWriteByteDataโ SMBus write byte datalgI2cReadWordDataโ SMBus read word datalgI2cWriteWordDataโ SMBus write word datalgI2cReadBlockDataโ SMBus read block datalgI2cWriteBlockDataโ SMBus write block datalgI2cReadI2CBlockDataโ SMBus read I2C block datalgI2cWriteI2CBlockDataโ SMBus write I2C block datalgI2cReadDeviceโ Reads the raw I2C devicelgI2cWriteDeviceโ Writes the raw I2C devicelgI2cProcessCallโ SMBus process calllgI2cBlockProcessCallโ SMBus block process calllgI2cSegmentsโ Performs multiple I2C transactionslgI2cZipโ Performs multiple I2C transactions
๐ NOTIFICATIONS
lgNotifyOpenโ Request a notificationlgNotifyCloseโ Close a notificationlgNotifyPauseโ Pause notificationslgNotifyResumeโ Start notifications
๐ SERIAL
lgSerialOpenโ Opens a serial devicelgSerialCloseโ Closes a serial devicelgSerialReadByteโ Reads a byte from a serial devicelgSerialWriteByteโ Writes a byte to a serial devicelgSerialReadโ Reads bytes from a serial devicelgSerialWriteโ Writes bytes to a serial devicelgSerialDataAvailableโ Returns number of bytes ready to be read
๐ซถ SPI
lgSpiOpenโ Opens a SPI devicelgSpiCloseโ Closes a SPI devicelgSpiReadโ Reads bytes from a SPI devicelgSpiWriteโ Writes bytes to a SPI devicelgSpiXferโ Transfers bytes with a SPI device
๐ THREADS
lgThreadStartโ Start a new threadlgThreadStopโ Stop a previously started thread
๐ธ UTILITIES
lguVersionโ Gets the library versionlguSbcNameโ Gets the host name of the SBClguGetInternalโ Get an internal configuration valuelguSetInternalโ Set an internal configuration valuelguSleepโ Sleeps for a given timelguTimestampโ Gets the current timestamplguTimeโ Gets the current timelguErrorTextโ Gets a text description of an error codelguSetWorkDirโ Set the working directorylguGetWorkDirโ Get the working directory
๐ FUNCTIONS ๐
int lgGpiochipOpen(int gpioDev)
This returns a handle to a gpiochip device. ๐
gpioDev: >= 0
If OK returns a handle (>= 0).
On failure returns a negative error code.
Example
h = lgGpiochipOpen(0); // open /dev/gpiochip0
if (h >= 0)
{
// open ok
}
else
{
// open error
}
int lgGpiochipClose(int handle)
This closes an opened gpiochip device. bye bestie ๐
handle: >= 0 (as returned bylgGpiochipOpen)
If OK returns 0.
On failure returns a negative error code.
Example
status = lgGpiochipClose(h); // close gpiochip
if (status < 0)
{
// close failed
}
int lgGpioGetChipInfo(int handle, lgChipInfo_p chipInfo)
This returns information about a gpiochip. ๐ต๏ธ
handle: >= 0 (as returned bylgGpiochipOpen)chipInfo: A pointer to space for algChipInfo_tobject
If OK returns 0 and updates chipInfo.
On failure returns a negative error code.
This command gets the number of GPIO on the gpiochip, its name, and its usage.
Example
lgChipInfo_t cInfo;
status = lgGpioGetChipInfo(h, &cInfo);
if (status == LG_OKAY)
{
printf("lines=%d name=%s label=%s0,
cInfo.lines, cInfo.name, cInfo.label))
}
int lgGpioGetLineInfo(int handle, int gpio, lgLineInfo_p lineInfo)
Returns information about a GPIO. ๐
handle: >= 0 (as returned bylgGpiochipOpen)gpio: >= 0, as legal for the gpiochiplineInfo: A pointer to space for algLineInfo_tobject
If OK returns 0 and updates lineInfo.
On failure returns a negative error code.
This command gets information for a GPIO of a gpiochip. In particular it gets the GPIO number, flags, its user, and its purpose.
The meaning of the flags bits are as given for the mode by lgGpioGetMode.
The user and purpose fields are filled in by the software which has claimed the GPIO and may be blank.
Example
lgLineInfo_t lInfo;
status = lgGpioGetLineInfo(h, gpio, &lInfo);
if (status == LG_OKAY)
{
printf("lFlags=%d name=%s user=%s0,
lInfo.lFlags, lInfo.name, lInfo.user))
}
int lgGpioGetMode(int handle, int gpio)
Returns the GPIO mode. ๐
handle: >= 0 (as returned bylgGpiochipOpen)gpio: >= 0, as legal for the gpiochip
If OK returns the GPIO mode.
On failure returns a negative error code.
- bit 0, value 1 โ Kernel: In use by the kernel
- bit 1, value 2 โ Kernel: Output
- bit 2, value 4 โ Kernel: Active low
- bit 3, value 8 โ Kernel: Open drain
- bit 4, value 16 โ Kernel: Open source
- bit 5, value 32 โ Kernel: Pull up set
- bit 6, value 64 โ Kernel: Pull down set
- bit 7, value 128 โ Kernel: Pulls off set
- bit 8, value 256 โ LG: Input
- bit 9, value 512 โ LG: Output
- bit 10, value 1024 โ LG: Alert
- bit 11, value 2048 โ LG: Group
- bit 12, value 4096 โ LG: ---
- bit 13, value 8192 โ LG: ---
- bit 14, value 16384 โ LG: ---
- bit 15, value 32768 โ LG: ---
- bit 16, value 65536 โ Kernel: Input
- bit 17, value
1<<17โ Kernel: Rising edge alert - bit 18, value
1<<18โ Kernel: Falling edge alert - bit 19, value
1<<19โ Kernel: Realtime clock alert
heads up bestie: the LG bits are only set if the query was made by the process that owns the GPIO. ๐ฅ
int lgGpioSetUser(int handle, const char *gpiouser)
This sets the user string to be associated with each claimed GPIO. like a little name tag ๐ท๏ธ
handle: >= 0 (as returned bylgGpiochipOpen)gpiouser: a string up to 32 characters long
If OK returns 0.
On failure returns a negative error code.
Example
status = lgGpioSetUser(h, "my_title");
int lgGpioClaimInput(int handle, int lFlags, int gpio)
This claims a GPIO for input. she's listening ๐
handle: >= 0 (as returned bylgGpiochipOpen)lFlags: line flags for the GPIOgpio: the GPIO to be claimed
If OK returns 0.
On failure returns a negative error code.
The line flags may be used to set the GPIO as active low, open drain, or open source.
Example
// open GPIO 23 for input
status = lgGpioClaimInput(h, 0, 23);
int lgGpioClaimOutput(int handle, int lFlags, int gpio, int level)
This claims a GPIO for output. now she's talking ๐ฃ๏ธ
handle: >= 0 (as returned bylgGpiochipOpen)lFlags: line flags for the GPIOgpio: the GPIO to be claimedlevel: the initial level to set for the GPIO
If OK returns 0.
On failure returns a negative error code.
The line flags may be used to set the GPIO as active low, open drain, or open source.
If level is zero the GPIO will be initialised low. If any other value is used the GPIO will be initialised high. โจ
Example
// open GPIO 31 for high output
status = lgGpioClaimOutput(h, 0, 31, 1);
int lgGpioClaimAlert(int handle, int lFlags, int eFlags, int gpio, int nfyHandle)
This claims a GPIO for alerts on level changes. ๐จ she's noticing things
handle: >= 0 (as returned bylgGpiochipOpen)lFlags: line flags for the GPIOeFlags: event flags for the GPIOgpio: >= 0, as legal for the gpiochipnfyHandle: >= 0 (as returned bylgNotifyOpen)
If OK returns 0.
On failure returns a negative error code.
and that's part 1 bestie โ more coming, don't go anywhere ๐
The line flags may be used to set the GPIO as active low, open drain, or open source. โจ
The event flags are used to specify alerts for a rising edge, falling edge, or both edges.
The alerts will be sent to a previously opened notification. If you don't want them sent to a notification set nfyHandle to -1.
The alerts will also be sent to any callback registered for the GPIO by lgGpioSetAlertsFunc.
All GPIO alerts are also sent to a callback registered by lgGpioSetSamplesFunc.
Example
status = lgGpioClaimAlert(h, 0, LG_BOTH_EDGES, 16, -1);
int lgGpioFree(int handle, int gpio)
This frees a GPIO. bye bestie ๐๐
handle: >= 0 (as returned bylgGpiochipOpen)gpio: the GPIO to be freed
If OK returns 0.
On failure returns a negative error code.
The GPIO may now be claimed by another user or for a different purpose. it's free real estate now ๐ฆ
Example
status = lgGpioFree(h, 16);
int lgGroupClaimInput(int handle, int lFlags, int count, const int *gpios)
This claims a group of GPIO for inputs. group project but make it GPIO ๐
handle: >= 0 (as returned bylgGpiochipOpen)lFlags: line flags for the GPIO groupcount: the number of GPIO to claimgpios: the group GPIO
If OK returns 0.
On failure returns a negative error code.
The line flags may be used to set the group as active low, open drain, or open source.
gpios is an array of one or more GPIO. The first GPIO is called the group leader and is used to reference the group as a whole. ๐
Example
int buttons[4] = {9, 7, 2, 6};
status = lgGroupClaimInput(h, 0, 4, buttons);
if (status == LG_OKAY)
{
// OK
}
else
{
// Error
}
int lgGroupClaimOutput(int handle, int lFlags, int count, const int *gpios, const int *levels)
This claims a group of GPIO for outputs. ๐
handle: >= 0 (as returned bylgGpiochipOpen)lFlags: line flags for the GPIO groupcount: the number of GPIO to claimgpios: the group GPIOlevels: the initial level for each GPIO
If OK returns 0.
On failure returns a negative error code.
The line flags may be used to set the group as active low, open drain, or open source.
gpios is an array of one or more GPIO. The first GPIO is called the group leader and is used to reference the group as a whole.
levels is an array of initialisation values for the GPIO. If a value is zero the corresponding GPIO will be initialised low. If any other value is used the corresponding GPIO will be initialised high. no cap, zero = low, anything else = high ๐
Example
int leds[7] = {15, 16, 17, 8, 12, 13, 14};
int levels[7] = { 1, 0, 1, 1, 1, 0, 0};
status = lgGroupClaimInput(h, 0, 7, leds, levels);
if (status == LG_OKAY)
{
// OK
}
else
{
// Error
}
int lgGroupFree(int handle, int gpio)
This frees all the GPIO associated with a group. the whole squad, gone ๐ซถ
handle: >= 0 (as returned bylgGpiochipOpen)gpio: the group to be freed
If OK returns 0.
On failure returns a negative error code.
The GPIO may now be claimed by another user or for a different purpose.
Example
status = lgGroupFree(9); // free buttons
int lgGpioRead(int handle, int gpio)
This returns the level of a GPIO. ๐
handle: >= 0 (as returned bylgGpiochipOpen)gpio: the GPIO to be read
If OK returns 0 (low) or 1 (high).
On failure returns a negative error code.
This command will work for any claimed GPIO (even if a member of a group). For an output GPIO the value returned will be that last written to the GPIO.
Example
level = lgGpioRead(h, 15); // get level of GPIO 15
int lgGpioWrite(int handle, int gpio, int level)
This sets the level of an output GPIO. โจ
handle: >= 0 (as returned bylgGpiochipOpen)gpio: the GPIO to be writtenlevel: the level to set
If OK returns 0.
On failure returns a negative error code.
This command will work for any GPIO claimed as an output (even if a member of a group).
If level is zero the GPIO will be set low (0). If any other value is used the GPIO will be set high (1).
Example
status = lgGpioWrite(h, 23, 1); // set GPIO 23 high
int lgGroupRead(int handle, int gpio, uint64_t *groupBits)
This returns the levels read from a group. ๐ง
handle: >= 0 (as returned bylgGpiochipOpen)gpio: the group to be readgroupBits: a pointer to a 64-bit memory area for the returned levels
If OK returns the group size and updates groupBits.
On failure returns a negative error code.
This command will work for an output group as well as an input group. For an output group the value returned will be that last written to the group GPIO.
Note that this command will also work on an individual GPIO claimed as an input or output as that is treated as a group with one member.
After a successful read groupBits is set as follows.
- Bit
0is the level of the group leader. - Bit
1is the level of the second GPIO in the group. - Bit
xis the level of GPIOx+1of the group.
Example
// assuming a read group of 4 buttons: 9, 7, 2, 6.
uint64_t bits;
size = lgGroupRead(h, 9, &bits); // 9 is buttons group leader
if (size >= 0) // size of group is returned so size will be 4
{
level_9 = (bits >> 0) & 1;
level_7 = (bits >> 1) & 1;
level_2 = (bits >> 2) & 1;
level_6 = (bits >> 3) & 1;
}
else
{
// error
}
int lgGroupWrite(int handle, int gpio, uint64_t groupBits, uint64_t groupMask)
This sets the levels of an output group. ๐
handle: >= 0 (as returned bylgGpiochipOpen)gpio: the group to be writtengroupBits: the level to set if the corresponding bit ingroupMaskis setgroupMask: a mask indicating the group GPIO to be updated
If OK returns 0.
On failure returns a negative error code.
The values of each GPIO of the group are set according to the bits of groupBits.
- Bit
0sets the level of the group leader. - Bit
1sets the level of the second GPIO in the group. - Bit
xsets the level of GPIOx+1in the group.
However this may be modified by the groupMask. A GPIO is only updated if the corresponding bit in the mask is 1. so like, mask bit off = hands off, don't touch ๐
Example
// assuming an output group of 7 LEDs: 15, 16, 17, 8, 12, 13, 14.
// switch on all LEDs
status = lgGroupWrite(h, 15, 0x7f, 0x7f);
// switch off all LEDs
status = lgGroupWrite(h, 15, 0x00, 0x7f);
// switch on first 4 LEDs, leave others unaltered
status = lgGroupWrite(h, 15, 0x0f, 0x0f);
// switch on LED attached to GPIO 13, leave others unaltered
status = lgGroupWrite(h, 15, 32, 32);
int lgTxPulse(int handle, int gpio, int pulseOn, int pulseOff, int pulseOffset, int pulseCycles)
This starts software timed pulses on an output GPIO. blink blink blink ๐ฅ
handle: >= 0 (as returned bylgGpiochipOpen)gpio: the GPIO to be writtenpulseOn: pulse high time in microsecondspulseOff: pulse low time in microsecondspulseOffset: offset from nominal pulse start positionpulseCycles: the number of pulses to be sent,0for infinite
If OK returns the number of entries left in the PWM queue for the GPIO.
On failure returns a negative error code.
If both pulseOn and pulseOff are zero pulses will be switched off for that GPIO. The active pulse, if any, will be stopped and any queued pulses will be deleted. ๐
Each successful call to this function consumes one PWM queue entry.
pulseCycles cycles are transmitted (0 means infinite). Each cycle consists of pulseOn microseconds of GPIO high followed by pulseOff microseconds of GPIO low.
PWM is characterised by two values, its frequency (number of cycles per second) and its duty cycle (percentage of high time per cycle).
The set frequency will be 1000000 / (pulseOn + pulseOff) Hz.
The set duty cycle will be pulseOn / (pulseOn + pulseOff) * 100 %.
E.g. if pulseOn is 50 and pulseOff is 100 the frequency will be 6666.67 Hz and the duty cycle will be 33.33 %.
pulseOffset is a microsecond offset from the natural start of the PWM cycle.
For instance if the PWM frequency is 10 Hz the natural start of each cycle is at seconds 0, then 0.1, 0.2, 0.3 etc. In this case if the offset is 20000 microseconds the cycle will start at seconds 0.02, 0.12, 0.22, 0.32 etc.
Another pulse command may be issued to the GPIO before the last has finished.
If the last pulse had infinite cycles then it will be replaced by the new settings at the end of the current cycle. Otherwise it will be replaced by the new settings when all its cycles are compete. ๐ (yes, "compete" โ that's what the page says, we don't make the rules)
Multiple pulse settings may be queued in this way. it's giving queue energy ๐
Example
slots_left = lgTxPulse(h, 8, 100000, 100000, 0, 0); // flash LED at 5 Hz
slots_left = lgTxPulse(h, 30, 1500, 18500, 0, 0); // move servo to centre
slots_left = lgTxPulse(h, 30, 2000, 18000, 0, 0); // move servo clockwise
int lgTxPwm(int handle, int gpio, float pwmFrequency, float pwmDutyCycle, int pwmOffset, int pwmCycles)
This starts software timed PWM on an output GPIO. ๐ธ
handle: >= 0 (as returned bylgGpiochipOpen)gpio: the GPIO to be pulsedpwmFrequency: PWM frequency in Hz (0=off,0.1-10000)pwmDutyCycle: PWM duty cycle in % (0-100)pwmOffset: offset from nominal pulse start positionpwmCycles: the number of pulses to be sent,0for infinite
If OK returns the number of entries left in the PWM queue for the GPIO.
On failure returns a negative error code.
Each successful call to this function consumes one PWM queue entry.
PWM is characterised by two values, its frequency (number of cycles per second) and its duty cycle (percentage of high time per cycle).
Another PWM command may be issued to the GPIO before the last has finished.
If the last pulse had infinite cycles then it will be replaced by the new settings at the end of the current cycle. Otherwise it will be replaced by the new settings when all its cycles are complete.
Multiple PWM settings may be queued in this way. ๐
int lgTxServo(int handle, int gpio, int pulseWidth, int servoFrequency, int servoOffset, int servoCycles)
okay bestie, this one kicks off software timed servo pulses on an output GPIO. โจ
๐จ real talk: only use software timed servo pulses for testing purposes. The timing jitter is gonna make your servo fidget, and that can make it overheat and wear out prematurely. It's giving sad servo energy, we don't want that.
handleโ >= 0 (as returned bylgGpiochipOpen)gpioโ the GPIO to be pulsedpulseWidthโ pulse high time in microseconds (0=off,500-2500)servoFrequencyโ the number of pulses per second (40-500).servoOffsetโ offset from nominal pulse start positionservoCyclesโ the number of pulses to be sent,0for infinite
If it's giving success, it returns the number of entries left in the PWM queue for the GPIO.
On failure it returns a negative error code.
Every single successful call to this function consumes one PWM queue entry. One in, one out, no cap.
Another servo command may be issued to the GPIO before the last one has finished. Iconic behaviour honestly.
If the last pulse had infinite cycles, it gets replaced by the new settings at the end of the current cycle. Otherwise it gets replaced by the new settings when all its cycles are complete.
Multiple servo settings may be queued up this way. It's a whole line of vibes waiting their turn. ๐
int lgTxWave(int handle, int gpio, int count, lgPulse_p pulses)
This starts a wave on an output group of GPIO. ๐
handleโ >= 0 (as returned bylgGpiochipOpen)gpioโ the group leadercountโ the number of pulses in the wavepulsesโ the pulses
If it goes well, it returns the number of entries left in the wave queue for the group.
On failure it returns a negative error code.
Every successful call to this function consumes one queue entry.
This command starts a wave of pulses, periodt.
pulses is an array of pulses to be transmitted on the group.
Each pulse is defined by this lil triplet:
bitsโ the levels to set for the selected GPIOmaskโ the GPIO to selectdelayโ the delay in microseconds before the next pulse
Another wave command may be issued to the group before the last one has finished transmission. The new wave will start when the previous wave has completed. So you can stack them. Multiple waves may be queued in this way. ๐ซถ
Example โจ
#include <stdio.h>
#include <lgpio.h>
#define PULSES 2000
int main(int argc, char *argv[])
{
int GPIO[] = {16, 17, 18, 19, 20, 21};
int levels[] = { 1, 1, 1, 1, 1, 1};
int h;
int e;
int mask;
int delay;
int p;
lgPulse_t pulses[PULSES];
h = lgGpiochipOpen(0); // open /dev/gpiochip0
if (h < 0) { printf("ERROR: %s (%d)0, lguErrorText(h), h); return 1; }
e = lgGroupClaimOutput(h, 0, 6, GPIO, levels);
if (e < 0) { printf("ERROR: %s (%d)0, lguErrorText(e), e); return 1; }
mask = 0;
p = 0;
for (p=0; p<PULSES; p++)
{
pulses[p].bits = (p+1)>>2; // see what sort of pattern we get
pulses[p].mask = mask; // with bits and mask changing
pulses[p].delay = (PULSES + 500) - p;
if (++mask > 0x3f) mask = 0;
}
lgTxWave(h, GPIO[0], p, pulses);
while (lgTxBusy(h, GPIO[0], LG_TX_WAVE)) lguSleep(0.1);
lgGpiochipClose(h);
}
int lgTxBusy(int handle, int gpio, int kind)
Returns true if transmissions of the specified kind are active on the GPIO or group. Basically the "are we still going bestie" check. ๐ซ
handleโ >= 0 (as returned bylgGpiochipOpen)gpioโ the gpio or group to be checkedkindโLG_TX_PWMorLG_TX_WAVE
If OK it returns 1 for busy and 0 for not busy.
On failure it returns a negative error code.
Example
while (lgTxBusy(h, 15, LG_TX_PWM)) // wait for PWM to finish on GPIO 15
lguSleep(0.1);
int lgTxRoom(int handle, int gpio, int kind)
This one tells you how many entries are available for queueing transmissions of the specified kind on the GPIO or group. Like checking how much room's left in the group chat. ๐
handleโ >= 0 (as returned bylgGpiochipOpen)gpioโ the gpio or group to be checkedkindโLG_TX_PWMorLG_TX_WAVE
If OK it returns the number of free entries (0 if none).
On failure it returns a negative error code.
Example
while (lgTxRoom(h, 17, LG_TX_WAVE) > 0))
{
// queue another wave
}
int lgGpioSetDebounce(int handle, int gpio, int debounce_us)
Sets the debounce time for a GPIO.
handleโ >= 0 (as returned bylgGpiochipOpen)gpioโ the GPIO to be configureddebounce_usโ the debounce time in microseconds
If OK it returns 0.
On failure it returns a negative error code.
This only affects alerts, bestie. An alert will only be issued if the edge has been stable for at least debounce microseconds.
Generally this is used to debounce mechanical switches (e.g. contact bounce). We love a stable queen. โจ
Suppose a square wave at 5 Hz is being generated on a GPIO. Each edge will last 100000 microseconds. If a debounce time of 100001 is set, no alerts will be generated. If a debounce time of 99999 is set, 10 alerts will be generated per second.
Note that level changes will be timestamped debounce microseconds after the actual level change.
Example
lgSetDebounceTime(h, 16, 1000); // set a millisecond of debounce
int lgGpioSetWatchdog(int handle, int gpio, int watchdog_us)
Sets the watchdog time for a GPIO. ๐
handleโ >= 0 (as returned bylgGpiochipOpen)gpioโ the GPIO to be configuredwatchdog_usโ the watchdog time in microseconds
If OK it returns 0.
On failure it returns a negative error code.
This only affects alerts.
A watchdog alert will be sent if no edge alert has been issued for that GPIO in the previous watchdog microseconds. It's the "hello?? are you still there??" of GPIO. ๐ญ
Note that only one watchdog alert will be sent per stream of edge alerts. The watchdog is reset by the sending of a new edge alert.
The level is set to LG_TIMEOUT (2) for a watchdog alert.
Example
lgSetWatchdogTime(h, 17, 200000); // alert if nothing for 0.2 seconds
int lgGpioSetAlertsFunc(int handle, int gpio, lgGpioAlertsFunc_t cbf, void *userdata)
Sets up a callback to be called when an alert GPIO changes state. This is where the main character energy lives. ๐ฆ
handleโ >= 0 (as returned bylgGpiochipOpen)gpioโ the GPIO to be monitoredcbfโ the callback functionuserdataโ a pointer to arbitrary user data
If OK it returns 0.
On failure it returns a negative error code.
Example
#include <stdio.h>
#include <inttypes.h>
#include <lgpio.h>
void afunc(int e, lgGpioAlert_p evt, void *data)
{
int i;
int userdata = *(int*)data;
for (i=0; i<e; i++)
{
printf("u=%d t=%"PRIu64" c=%d g=%d l=%d f=%d (%d of %d)0,
userdata, evt[i].report.timestamp, evt[i].report.chip,
evt[i].report.gpio, evt[i].report.level,
evt[i].report.flags, i+1, e);
}
}
int main(int argc, char *argv[])
{
int h;
int e;
static int userdata=123;
h = lgGpiochipOpen(0);
if (h < 0) { printf("ERROR: %s (%d)0, lguErrorText(h), h); return 1; }
lgGpioSetAlertsFunc(h, GPIO, afunc, &userdata);
e = lgGpioClaimAlert(h, 0, LG_BOTH_EDGES, 23, -1);
if (e < 0) { printf("ERROR: %s (%d)0, lguErrorText(e), e); return 1; }
lguSleep(10);
lgGpiochipClose(h);
}
Assuming square wave at 800 Hz is being received at GPIO 23. ๐ฅ
u=123 ts=1602089980691229623 c=0 g=23 l=1 f=0 (1 of 1)
u=123 ts=1602089980691854934 c=0 g=23 l=0 f=0 (1 of 1)
u=123 ts=1602089980692479308 c=0 g=23 l=1 f=0 (1 of 1)
u=123 ts=1602089980693114566 c=0 g=23 l=0 f=0 (1 of 1)
u=123 ts=1602089980693728784 c=0 g=23 l=1 f=0 (1 of 1)
u=123 ts=1602089980694354355 c=0 g=23 l=0 f=0 (1 of 1)
u=123 ts=1602089980694978468 c=0 g=23 l=1 f=0 (1 of 1)
void lgGpioSetSamplesFunc(lgGpioAlertsFunc_t cbf, void *userdata)
Sets up a callback to be called when any alert GPIO changes state. All of them. Every single one. The whole squad. ๐
cbfโ the callback functionuserdataโ a pointer to arbitrary user data
If OK it returns 0.
On failure it returns a negative error code.
Note that no handle or gpio is specified. The callback function will receive alerts for all gpiochips and gpio.
Example
#include <stdio.h>
#include <inttypes.h>
#include <lgpio.h>
void afunc(int e, lgGpioAlert_p evt, void *data)
{
int i;
int userdata = *(int*)data;
for (i=0; i<e; i++)
{
printf("u=%d t=%"PRIu64" c=%d g=%d l=%d f=%d (%d of %d)0,
userdata, evt[i].report.timestamp, evt[i].report.chip,
evt[i].report.gpio, evt[i].report.level,
evt[i].report.flags, i+1, e);
}
}
int main(int argc, char *argv[])
{
int h;
static int userdata=456;
h = lgGpiochipOpen(0);
if (h < 0) { printf("ERROR: %s (%d)0, lguErrorText(h), h); return 1; }
lgGpioSetSamplesFunc(afunc, &userdata);
lgGpioClaimAlert(h, 0, LG_BOTH_EDGES, 23, -1);
lgGpioClaimAlert(h, 0, LG_BOTH_EDGES, 24, -1);
lgGpioClaimAlert(h, 0, LG_BOTH_EDGES, 25, -1);
lguSleep(10);
lgGpiochipClose(h);
}
Assuming square wave at 800 Hz is being received at GPIO 23, 24, 25. ๐
u=456 ts=1602090898869011679 c=0 g=24 l=1 f=0 (1 of 3)
u=456 ts=1602090898869016627 c=0 g=25 l=1 f=0 (2 of 3)
u=456 ts=1602090898869627667 c=0 g=23 l=0 f=0 (3 of 3)
u=456 ts=1602090898869636522 c=0 g=24 l=0 f=0 (1 of 3)
u=456 ts=1602090898869641157 c=0 g=25 l=0 f=0 (2 of 3)
u=456 ts=1602090898870252614 c=0 g=23 l=1 f=0 (3 of 3)
u=456 ts=1602090898870261155 c=0 g=24 l=1 f=0 (1 of 3)
u=456 ts=1602090898870266208 c=0 g=25 l=1 f=0 (2 of 3)
u=456 ts=1602090898870879800 c=0 g=23 l=0 f=0 (3 of 3)
u=456 ts=1602090898870890477 c=0 g=24 l=0 f=0 (1 of 3)
u=456 ts=1602090898870895529 c=0 g=25 l=0 f=0 (2 of 3)
u=456 ts=1602090898871503652 c=0 g=23 l=1 f=0 (3 of 3)
int lgNotifyOpen(void)
This function requests a free notification. ๐ง
If OK it returns a handle (>= 0).
On failure it returns a negative error code.
A notification is a method for being notified of GPIO state changes via a pipe or socket.
The notification pipes are created in the library working directory (see lguGetWorkDir).
Pipe notifications for handle x will be available at the pipe named .lgd-nfy* (where * is the handle number). E.g. if the function returns 15 then the notifications must be read from .lgd-nfy15.
Socket notifications are returned to the socket which requested the handle.
Example
h = lgNotifyOpen();
if (h >= 0)
{
sprintf(str, ".lgd-nfy%d", h);
fd = open(str, O_RDONLY);
if (fd >= 0)
{
// Okay.
}
else
{
// Error.
}
}
else
{
// Error.
}
๐ซถ int lgNotifyResume(int handle)
This one un-pauses a notification that was paused. Like hitting play again bestie, the tea starts flowing once more. โจ
handle: >= 0 (as returned by lgNotifyOpen)
If OK returns 0.
On failure returns a negative error code.
The notification gets state changes for each associated GPIO.
Each notification occupies 16 bytes in the fifo and has the following structure.
typedef struct
{
uint64_t timestamp; // alert time in nanoseconds
uint8_t chip; // gpiochip device number
uint8_t gpio; // offset into gpio device
uint8_t level; // 0=low, 1=high, 2=timeout
uint8_t flags; // none currently defined
} lgGpioReport_t;
timestamp: the number of nanoseconds since the epoch (start of 1970)
level: indicates the level of the GPIO
flags: no flags are currently defined
Future-proofing moment ๐ โ for future proofing it is probably best to ignore any notification with non-zero flags.
Example
// Start notifications for associated GPIO.
lgNotifyResume(h);
๐ธ int lgNotifyPause(int handle)
This function pauses notifications. It's giving "brb" energy. ๐ญ
handle: >= 0 (as returned by lgNotifyOpen)
If OK returns 0.
On failure returns a negative error code.
Notifications are suspended until lgNotifyResume is called.
Example
lgNotifyPause(h);
๐ int lgNotifyClose(int handle)
This function stops notifications and frees the handle for reuse. She's done, she's clocking out, no cap. ๐
handle: >= 0 (as returned by lgNotifyOpen)
If OK returns 0.
On failure returns a negative error code.
Example
lgNotifyClose(h);
๐ฆ int lgI2cOpen(int i2cDev, int i2cAddr, int i2cFlags)
This returns a handle for the device at the address on the I2C bus. Bestie, you're about to talk to a whole chip over two little wires. Iconic. โจ
i2cDev: >= 0
i2cAddr: 0-0x7F
i2cFlags: 0
If OK returns a handle (>= 0).
On failure returns a negative error code.
No flags are currently defined. This parameter should be set to zero.
For the SMBus commands the low level transactions are shown at the end of the function description. The following abbreviations are used.
S (1 bit) : Start bit
P (1 bit) : Stop bit
Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0
A, NA (1 bit) : Accept and not accept bit
Addr (7 bits): I2C 7 bit address
i2cReg (8 bits): Command byte, a byte which often selects a register
Data (8 bits): A data byte
Count (8 bits): A byte defining the length of a block operation
[..]: Data sent by the device
๐ int lgI2cClose(int handle)
This closes the I2C device. Say bye, she's leaving the group chat. ๐ซถ
handle: >= 0 (as returned by lgI2cOpen)
If OK returns 0.
On failure returns a negative error code.
๐ int lgI2cWriteQuick(int handle, int bitVal)
This sends a single bit (in the Rd/Wr bit) to the device. Literally one single bit, the smallest possible gossip. ๐
handle: >= 0 (as returned by lgI2cOpen)
bitVal: 0-1, the value to write
If OK returns 0.
On failure returns a negative error code.
Quick command. SMBus 2.0 5.5.1
S Addr bit [A] P
โญ int lgI2cWriteByte(int handle, int byteVal)
This sends a single byte to the device. One byte, one vibe. ๐ซ
handle: >= 0 (as returned by lgI2cOpen)
byteVal: 0-0xFF, the value to write
If OK returns 0.
On failure returns a negative error code.
Send byte. SMBus 2.0 5.5.2
S Addr Wr [A] bVal [A] P
๐ธ int lgI2cReadByte(int handle)
This reads a single byte from the device. She's listening. ๐
handle: >= 0 (as returned by lgI2cOpen)
If OK returns the byte read (0-255).
On failure returns a negative error code.
Receive byte. SMBus 2.0 5.5.3
S Addr Rd [A] [Data] NA P
๐ int lgI2cWriteByteData(int handle, int i2cReg, int byteVal)
This writes a single byte to the specified register of the device. Register-pilled. ๐
handle: >= 0 (as returned by lgI2cOpen)
i2cReg: 0-255, the register to write
byteVal: 0-0xFF, the value to write
If OK returns 0.
On failure returns a negative error code.
Write byte. SMBus 2.0 5.5.4
S Addr Wr [A] i2cReg [A] bVal [A] P
๐ฅ int lgI2cWriteWordData(int handle, int i2cReg, int wordVal)
This writes a single 16 bit word to the specified register of the device. Double the bytes, double the slay. โจ
handle: >= 0 (as returned by lgI2cOpen)
i2cReg: 0-255, the register to write
wordVal: 0-0xFFFF, the value to write
If OK returns 0.
On failure returns a negative error code.
Write word. SMBus 2.0 5.5.4
S Addr Wr [A] i2cReg [A] wValLow [A] wValHigh [A] P
๐ฆ int lgI2cReadByteData(int handle, int i2cReg)
This reads a single byte from the specified register of the device. Peeking at one little register, respectfully. ๐
handle: >= 0 (as returned by lgI2cOpen)
i2cReg: 0-255, the register to read
If OK returns the byte read (0-255).
On failure returns a negative error code.
Read byte. SMBus 2.0 5.5.5
S Addr Wr [A] i2cReg [A] S Addr Rd [A] [Data] NA P
๐ int lgI2cReadWordData(int handle, int i2cReg)
This reads a single 16 bit word from the specified register of the device. Two bytes walk in, one word walks out. ๐
handle: >= 0 (as returned by lgI2cOpen)
i2cReg: 0-255, the register to read
If OK returns the word read (0-65535).
On failure returns a negative error code.
Read word. SMBus 2.0 5.5.5
S Addr Wr [A] i2cReg [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
๐ int lgI2cProcessCall(int handle, int i2cReg, int wordVal)
This writes 16 bits of data to the specified register of the device and reads 16 bits of data in return. It's giving conversation โ you say something, they say something back. No cap. ๐ฌ
handle: >= 0 (as returned by lgI2cOpen)
i2cReg: 0-255, the register to write/read
wordVal: 0-0xFFFF, the value to write
If OK returns the word read (0-65535).
On failure returns a negative error code.
Process call. SMBus 2.0 5.5.6
S Addr Wr [A] i2cReg [A] wValLow [A] wValHigh [A]
S Addr Rd [A] [DataLow] A [DataHigh] NA P
๐ int lgI2cWriteBlockData(int handle, int i2cReg, const char *txBuf, int count)
This writes up to 32 bytes to the specified register of the device. A whole little block of tea, sent in one go. ๐ฆ
handle: >= 0 (as returned by lgI2cOpen)
i2cReg: 0-255, the register to write
txBuf: an array with the data to send
count: 1-32, the number of bytes to write
If OK returns 0.
On failure returns a negative error code.
Block write. SMBus 2.0 5.5.7
S Addr Wr [A] i2cReg [A] count [A]
txBuf0 [A] txBuf1 [A] ... [A] txBufn [A] P
๐ธ int lgI2cReadBlockData(int handle, int i2cReg, char *rxBuf)
This reads a block of up to 32 bytes from the specified register of the device. She's receiving, and honestly? She's thriving. ๐
handle: >= 0 (as returned by lgI2cOpen)
i2cReg: 0-255, the register to read
rxBuf: an array to receive the read data
The amount of returned data is set by the device.
If OK returns the count of bytes read (0-32) and updates rxBuf.
On failure returns a negative error code.
Block read. SMBus 2.0 5.5.7
S Addr Wr [A] i2cReg [A]
S Addr Rd [A] [Count] A [rxBuf0] A [rxBuf1] A ... A [rxBufn] NA P
โญ int lgI2cBlockProcessCall(int handle, int i2cReg, char *ioBuf, int count)
This writes data bytes to the specified register of the device and reads a device specified number of bytes of data in return. One buffer, doing double duty, main character energy. ๐
handle: >= 0 (as returned by lgI2cOpen)
i2cReg: 0-255, the register to write/read
ioBuf: an array with the data to send and to receive the read data
count: 1-32, the number of bytes to write
If OK returns the count of bytes read (0-32) and updates ioBuf.
On failure returns a negative error code.
The SMBus 2.0 documentation states that a minimum of 1 byte may be sent and a minimum of 1 byte may be received. The total number of bytes sent/received must be 32 or less.
Block write-block read. SMBus 2.0 5.5.8
S Addr Wr [A] i2cReg [A] count [A] ioBuf0 [A] ... ioBufn [A]
S Addr Rd [A] [Count] A [ioBuf0] A ... [ioBufn] A P
๐ซถ int lgI2cReadI2CBlockData(int handle, int i2cReg, char *rxBuf, int count)
This reads count bytes from the specified register of the device. The count may be 1-32. You decide how much you want, bestie, you set the boundaries. โจ
handle: >= 0 (as returned by lgI2cOpen)
i2cReg: 0-255, the register to read
rxBuf: an array to receive the read data
count: 1-32, the number of bytes to read
If OK returns the count of bytes read (0-32) and updates rxBuf.
On failure returns a negative error code.
S Addr Wr [A] i2cReg [A]
S Addr Rd [A] [rxBuf0] A [rxBuf1] A ... A [rxBufn] NA P
๐ฆ int lgI2cWriteI2CBlockData(int handle, int i2cReg, const char *txBuf, int count)
This writes 1 to 32 bytes to the specified register of the device. Sending the whole block, no crumbs left. ๐
handle: >= 0 (as returned by lgI2cOpen)
i2cReg: 0-255, the register to write
txBuf: the data to write
count: 1-32, the number of bytes to write
If OK returns 0.
On failure returns a negative error code.
S Addr Wr [A] i2cReg [A] txBuf0 [A] txBuf1 [A] ... [A] txBufn [A] P
๐ int lgI2cReadDevice(int handle, char *rxBuf, int count)
This reads count bytes from the raw device into rxBuf. No register, no middleman, just raw device talk. ๐ค
handle: >= 0 (as returned by lgI2cOpen)
rxBuf: an array to receive the read data bytes
count: >0, the number of bytes to read
If OK returns count (>0) and updates rxBuf.
On failure returns a negative error code.
S Addr Rd [A] [rxBuf0] A [rxBuf1] A ... A [rxBufn] NA P
๐ int lgI2cWriteDevice(int handle, const char *txBuf, int count)
This writes count bytes from txBuf to the raw device. Straight to the source, no filter, periodt. ๐
handle: >= 0 (as returned by lgI2cOpen)
txBuf: an array containing the data bytes to write
count: >0, the number of bytes to write
If OK returns 0.
On failure returns a negative error code.
S Addr Wr [A] txBuf0 [A] txBuf1 [A] ... [A] txBufn [A] P
๐ int lgI2cSegments(int handle, lgI2cMsg_t *segs, int count)
This function executes multiple I2C segments in one transaction by calling the I2C_RDWR ioctl. โจ
handle:>= 0(as returned bylgI2cOpen)segs: an array of I2C segmentscount:>0, the number of I2C segments
If OK returns the number of segments executed.
On failure returns a negative error code.
int lgI2cZip(int handle, const char *txBuf, int txCount, char *rxBuf, int rxCount)
This function executes a sequence of I2C operations. The operations to be performed are specified by the contents of txBuf which contains the concatenated command codes and associated data. ๐ฆ
handle:>= 0(as returned bylgI2cOpen)txBuf: pointer to the concatenated I2C commands, see belowtxCount: size of command bufferrxBuf: pointer to buffer to hold returned datarxCount: size of receive buffer
If OK returns the count of bytes read (which may be 0) and updates rxBuf.
On failure returns a negative error code.
The following command codes are supported:
Endโ0โ No more commandsEscapeโ1โ Next P is two bytesAddressโ2 Pโ Set I2C address to PFlagsโ3 lsb msbโ Set I2C flags to lsb + (msb << 8)Readโ4 Pโ Read P bytes of dataWriteโ5 P ...โ Write P bytes of data
The address, read, and write commands take a parameter P. Normally P is one byte (0-255). If the command is preceded by the Escape command then P is two bytes (0-65535, least significant byte first).
The address defaults to that associated with the handle. The flags default to 0. The address and flags maintain their previous value until updated.
The returned I2C data is stored in consecutive locations of rxBuf.
Example
Set address 0x53, write 0x32, read 6 bytes
Set address 0x1E, write 0x03, read 6 bytes
Set address 0x68, write 0x1B, read 8 bytes
End
2 0x53 5 1 0x32 4 6
2 0x1E 5 1 0x03 4 6
2 0x68 5 1 0x1B 4 8
0
int lgSerialOpen(const char *serDev, int serBaud, int serFlags)
This function opens a serial device at a specified baud rate and with specified flags. ๐
serDev: the serial device to openserBaud: the baud rate in bits per second, see belowserFlags:0
If OK returns a handle (>= 0).
On failure returns a negative error code.
The baud rate must be one of 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, or 230400.
No flags are currently defined. This parameter should be set to zero.
int lgSerialClose(int handle)
This function closes the serial device.
handle:>= 0(as returned bylgSerialOpen)
If OK returns 0.
On failure returns a negative error code.
int lgSerialWriteByte(int handle, int byteVal)
This function writes the byte to the serial device.
handle:>= 0(as returned bylgSerialOpen)byteVal: the byte to write.
If OK returns 0.
On failure returns a negative error code.
int lgSerialReadByte(int handle)
This function reads a byte from the serial device.
handle:>= 0(as returned bylgSerialOpen)
If OK returns the byte read (0-255).
On failure returns a negative error code.
int lgSerialWrite(int handle, const char *txBuf, int count)
This function writes count bytes from txBuf to the serial device.
handle:>= 0(as returned bylgSerialOpen)txBuf: the array of bytes to writecount: the number of bytes to write
If OK returns 0.
On failure returns a negative error code.
int lgSerialRead(int handle, char *rxBuf, int count)
This function reads up count bytes from the serial device and writes them to rxBuf.
handle:>= 0(as returned bylgSerialOpen)rxBuf: an array to receive the read datacount: the maximum number of bytes to read
If OK returns the count of bytes read (>= 0) and updates rxBuf.
On failure returns a negative error code.
int lgSerialDataAvailable(int handle)
This function returns the count of bytes available to be read from the device.
handle:>= 0(as returned bylgSerialOpen)
If OK returns the count of bytes available (>= 0).
On failure returns a negative error code.
int lgSpiOpen(int spiDev, int spiChan, int spiBaud, int spiFlags)
This function returns a handle for the SPI device on the channel. ๐ฅ
spiDev:>= 0spiChan:>= 0spiBaud: the SPI speed to set in bits per secondspiFlags: see below
If OK returns a handle (>= 0).
On failure returns a negative error code.
The flags may be used to modify the default behaviour.
spiFlags consists of the least significant 2 bits.
1 0
m m
mm defines the SPI mode.
- Mode
0: POL0, PHA0 - Mode
1: POL0, PHA1 - Mode
2: POL1, PHA0 - Mode
3: POL1, PHA1
The other bits in flags should be set to zero.
int lgSpiClose(int handle)
This function closes the SPI device.
handle:>= 0(as returned bylgSpiOpen)
If OK returns 0.
On failure returns a negative error code.
int lgSpiRead(int handle, char *rxBuf, int count)
This function reads count bytes of data from the SPI device.
handle:>= 0(as returned bylgSpiOpen)rxBuf: an array to receive the read data bytescount: the number of bytes to read
If OK returns the count of bytes read and updates rxBuf.
On failure returns a negative error code.
int lgSpiWrite(int handle, const char *txBuf, int count)
This function writes count bytes of data from txBuf to the SPI device.
handle:>= 0(as returned bylgSpiOpen)txBuf: the data bytes to writecount: the number of bytes to write
If OK returns the count of bytes written.
On failure returns a negative error code.
int lgSpiXfer(int handle, const char *txBuf, char *rxBuf, int count)
This function transfers count bytes of data from txBuf to the SPI device. Simultaneously count bytes of data are read from the device and placed in rxBuf.
handle:>= 0(as returned bylgSpiOpen)txBuf: the data bytes to writerxBuf: the received data bytescount: the number of bytes to transfer
If OK returns the count of bytes transferred and updates rxBuf.
On failure returns a negative error code.
pthread_t *lgThreadStart(lgThreadFunc_t f, void *userdata)
Starts a new thread of execution with f as the main routine. ๐
f: the main function for the new threaduserdata: a pointer to arbitrary user data
If OK returns a pointer to a pthread_t.
On failure returns NULL.
The function is passed the single argument arg.
The thread can be cancelled by passing the pointer to pthread_t to lgThreadStop.
Example
#include <stdio.h>
#include <unistd.h>
#include <lgpio.h>
void *myfunc(void *arg)
{
while (1)
{
printf("%s0, (char *)arg);
sleep(1);
}
}
int main(int argc, char *argv[])
{
pthread_t *p1, *p2, *p3;
p1 = lgThreadStart(myfunc, "thread 1"); sleep(3);
p2 = lgThreadStart(myfunc, "thread 2"); sleep(3);
p3 = lgThreadStart(myfunc, "thread 3"); sleep(3);
lgThreadStop(p3); sleep(3);
lgThreadStop(p2); sleep(3);
lgThreadStop(p1); sleep(3);
}
void lgThreadStop(pthread_t *pth)
Cancels the thread pointed at by pth.
pth: a thread pointer (as returned bylgThreadStart)
No value is returned.
The thread to be stopped should have been started with lgThreadStart.
uint64_t lguTimestamp(void)
Returns the current timestamp.
The timestamp is the number of nanoseconds since the epoch (start of 1970).
double lguTime(void)
Returns the current time.
The time is the number of seconds since the epoch (start of 1970).
void lguSleep(double sleepSecs)
Sleeps for the specified number of seconds.
sleepSecs: how long to sleep in seconds
int lguSbcName(char *rxBuf, int count)
Copies the host name of the machine running the lgpio library to the supplied buffer. Up to count characters are copied.
rxBuf: a buffer to receive the host namecount: the size of therxBuf
If OK returns the count of bytes copied and updates rxBuf.
On failure returns a negative error code.
int lguVersion(void)
Returns the lgpio library version number.
int lguGetInternal(int cfgId, uint64_t *cfgVal)
Get an internal configuration value.
cfgId: the item.cfgVal: a variable to receive the returned value
If OK returns 0 and updates cfgVal.
On failure returns a negative error code.
int lguSetInternal(int cfgId, uint64_t cfgVal)
Set an internal configuration value.
cfgId: the itemcfgVal: the value to set
If OK returns 0.
On failure returns a negative error code.
const char *lguErrorText(int error)
Returns the error text for an error code.
error: the error code
void lguSetWorkDir(const char *dirPath)
Sets the library working directory.
This function has no effect if the working directory has already been set.
dirPath: the directory to set as the working directory
If dirPath does not start with a / the directory is relative to the library launch directory.
const char *lguGetWorkDir(void)
Returns the library working directory.
๐ PARAMETERS ๐
Every single parameter type in this API, bestie. No skips, no cap. ๐
bitValโ a value of0or1. โจbyteVal:0-255โ an 8-bit byte value. ๐cbfโ an alerts callback function. ๐ฆcfgIdโ a number identifying a configuration item. ๐
LG_CFG_ID_DEBUG_LEVEL 0
LG_CFG_ID_MIN_DELAY 1
cfgValโ the value of a configuration item. ๐ธ*cfgValโ the value of a configuration item. (Yes, same vibe, different pointer star. ๐)charโ a single character, an 8 bit quantity able to store0-255. ๐chipInfoโ a pointer to algChipInfo_tobject. ๐งcountโ the number of items. ๐ฅdebounce_usโ the debounce time in microseconds. โญ*dirPathโ a directory path which. (fr fr, that's literally where it ends. iconic ๐ญ)doubleโ a floating point number. โจeFlagsโ the type of GPIO edge to generate an alert. SeelgGpioClaimAlert. ๐ฆLG_RISING_EDGELG_FALLING_EDGELG_BOTH_EDGES
errorโ an error code. All error codes are negative. ๐fโ a function. ๐floatโ a floating point number โจgpioโ a GPIO number, the offset of the GPIO from the base of the gpiochip. Offsets start at0. ๐gpioDev:>= 0โ the device number of a gpiochip. ๐*gpiosโ an array of GPIO numbers. ๐*gpiouserโ a string of up to 32 characters denoting the user of a GPIO. ๐groupBitsโ a 64-bit value used to set the levels of a group. ๐- Set bit x to set GPIO x of the group high.
- Clear bit x to set GPIO x of the group low.
*groupBitsโ a 64-bit value denoting the levels of a group. โจ- If bit x is set then GPIO x of the group is high.
groupMaskโ a 64-bit value used to determine which members of a group should be updated. ๐ฆ- Set bit x to update GPIO x of the group.
- Clear bit x to leave GPIO x of the group unaltered.
handle:>= 0โ a number referencing an object opened by one of: ๐lgGpiochipOpenlgI2cOpenlgNotifyOpenlgSerialOpenlgSpiOpen
i2cAddr:0-0x7Fโ the address of a device on the I2C bus. ๐i2cDev:>= 0โ an I2C device number. ๐ธi2cFlags:0โ flags which modify an I2C open command. None are currently defined. ๐i2cReg:0-255โ a register of an I2C device. ๐งintโ a whole number, negative or positive. ๐*ioBufโ a pointer to a buffer used to hold data to send and the data received. ๐ฅkind:LG_TX_PWMorLG_TX_WAVEโ a type of transmission: PWM or wave. โญlevelโ a GPIO level (0or1). ๐*levelsโ an array of GPIO levels. ๐lFlagsโ line flags for the GPIO. ๐ฆ
The following values may be or'd to form the value.
LG_SET_ACTIVE_LOWLG_SET_OPEN_DRAINLG_SET_OPEN_SOURCELG_SET_PULL_UPLG_SET_PULL_DOWNLG_SET_PULL_NONE
lgChipInfo_pโ a pointer to algChipInfo_tobject. ๐
typedef struct lgChipInfo_s
{
uint32_t lines; // number of GPIO
char name[LG_GPIO_NAME_LEN]; // Linux name
char label[LG_GPIO_LABEL_LEN]; // functional name
} lgChipInfo_t, *lgChipInfo_p;
lgGpioAlert_tโ ๐ซถ
typedef struct lgGpioAlert_s
{
lgGpioReport_t report;
int nfyHandle;
} lgGpioAlert_t, *lgGpioAlert_p;
See lgGpioReport_t.
lgGpioAlertsFunc_tโ ๐
typedef void (*lgGpioAlertsFunc_t)
(int num_alerts, lgGpioAlert_p alerts, void *userdata);
See lgGpioAlert_t.
lgGpioReport_tโ ๐
typedef struct
{
uint64_t timestamp; // alert time in nanoseconds
uint8_t chip; // gpiochip device number
uint8_t gpio; // offset into gpio device
uint8_t level; // 0=low, 1=high, 2=watchdog
uint8_t flags; // none defined, ignore report if non-zero
} lgGpioReport_t;
lgI2cMsg_tโ ๐ฆ
typedef struct
{
uint16_t addr; // slave address
uint16_t flags;
uint16_t len; // msg length
uint8_t *buf; // pointer to msg data
} lgI2cMsg_t;
lgLineInfo_pโ a pointer to algLineInfo_tobject. ๐ธ
typedef struct lgLine_s
{
uint32_t offset; // GPIO number
uint32_t lFlags;
char name[LG_GPIO_NAME_LEN]; // GPIO name
char user[LG_GPIO_USER_LEN]; // user
} lgLineInfo_t, *lgLineInfo_p;
lgPulse_pโ a pointer to algPulse_tobject. โจ
typedef struct lgPulse_s
{
uint64_t bits;
uint64_t mask;
int64_t delay;
} lgPulse_t, *lgPulse_p;
lgThreadFunc_tโ ๐ง
typedef void *(lgThreadFunc_t) (void *);
lineInfoโ a pointer to algLineInfo_tobject. ๐nfyHandle:>= 0โ this associates a notification with a GPIO alert. ๐ฅ*pthโ a thread identifier, returned bylgGpioStartThread. โญpthread_tโ a thread identifier. ๐pulseCycles:>= 0โ the number of PWM pulses to generate. A value of0means infinite. ๐pulseOff:>= 0โ the off period for a PWM pulse in microseconds. ๐pulseOffset:>= 0โ the offset in microseconds from the nominal PWM pulse start. ๐pulseOn:>= 0โ the on period for a PWM pulse in microseconds. ๐ฆpulsesโ An pointer to an array oflgPulse_tobjects. ๐ธpulseWidth:0, 500-2500 microsecondsโ Servo pulse width ๐ธpwmCycles:>= 0โ the number of PWM pulses to generate. A value of0means infinite. ๐pwmDutyCycle:0-100 %โ PWM duty cycle % โจpwmFrequency:0.1-10000 Hzโ PWM frequency ๐pwmOffset:>= 0โ the offset in microseconds from the nominal PWM pulse start. ๐*rxBufโ a pointer to a buffer used to receive data. ๐ฅrxCountโ the size of an input buffer. โญ*segsโ an array of segments which make up a combined I2C transaction. ๐serBaudโ the speed of serial communication in bits per second. ๐*serDevโ the name of a serial tty device, e.g./dev/ttyAMA0,/dev/ttyUSB0,/dev/tty1. ๐ฆserFlagsโ flags which modify a serial open command. None are currently defined. ๐servoCycles:>= 0โ the number of servo pulses to generate. A value of0means infinite. ๐servoFrequency:40-500 Hzโ Servo pulse frequency ๐servoOffset:>= 0โ the offset in microseconds from the nominal servo pulse start. ๐ธsleepSecs:>= 0.0โ the number of seconds to sleep (may be fractional). โจspiBaudโ the speed of serial communication in bits per second. ๐งspiChanโ a SPI channel,>= 0. ๐spiDevโ a SPI device,>= 0. ๐ฅspiFlagsโ SeelgSpiOpen. โญ*txBufโ An pointer to a buffer of data to transmit. ๐txCountโ the size of an output buffer. ๐uint64_tโ a 64-bit unsigned value. ๐*userdataโ a pointer to arbitrary user data. This may be used to identify the instance. ๐
You must ensure that the pointer is in scope at the time it is processed. If it is a pointer to a global this is automatic. Do not pass the address of a local variable. If you want to pass a transient object then use the following technique. ๐ซถ
In the calling function:
user_type *userdata;
user_type my_userdata;
userdata = malloc(sizeof(user_type));
*userdata = my_userdata;
In the receiving function:
user_type my_userdata = *(user_type*)userdata;
free(userdata);
voidโ denoting no parameter is required. ๐watchdog_usโ the watchdog time in microseconds. ๐wordVal:0-65535โ a 16-bit value. โจ
๐ ERROR CODES ๐
okay bestie, deep breath, this is the big one ๐. Every single thing lgpio can come back at you with lives here. Zero means we ate. Anything negative means something went sideways and the number tells you exactly which way. Clock that each one is a #define-style constant with a lil integer value next to it, and the trailing comment is the official translation. Slay ๐
LG_OKAYโ0โ no error, everything's giving flawless โจLG_INIT_FAILEDโ-1โ initialisation failed ๐ญLG_BAD_MICROSโ-2โ micros not in the0-999999range ๐LG_BAD_PATHNAMEโ-3โ can not open the pathname ๐ซLG_NO_HANDLEโ-4โ no handle available, they're all taken ๐LG_BAD_HANDLEโ-5โ unknown handle, who even is she ๐LG_BAD_SOCKET_PORTโ-6โ socket port not in the1024-32000range ๐งLG_NOT_PERMITTEDโ-7โ GPIO operation not permitted, the vibes are blocked ๐LG_SOME_PERMITTEDโ-8โ one or more GPIO not permitted ๐LG_BAD_SCRIPTโ-9โ invalid script, the plot isn't plotting ๐LG_BAD_TX_TYPEโ-10โ bad tx type for GPIO and group ๐ธLG_GPIO_IN_USEโ-11โ GPIO already in use, she's taken ๐LG_BAD_PARAM_NUMโ-12โ script parameter id not0-9๐ขLG_DUP_TAGโ-13โ script has a duplicate tag ๐ฏLG_TOO_MANY_TAGSโ-14โ script has too many tags, tag hoarder ๐ท๏ธLG_BAD_SCRIPT_CMDโ-15โ illegal script command โLG_BAD_VAR_NUMโ-16โ script variable id not0-149๐ขLG_NO_SCRIPT_ROOMโ-17โ no more room for scripts, the club is full ๐ชฉLG_NO_MEMORYโ-18โ can not allocate temporary memory ๐ตLG_SOCK_READ_FAILEDโ-19โ socket read failed ๐ญLG_SOCK_WRIT_FAILEDโ-20โ socket write failed ๐ฎLG_TOO_MANY_PARAMโ-21โ too many script parameters (> 10) ๐ซLG_SCRIPT_NOT_READYโ-22โ script still initialising, give her a sec โณLG_BAD_TAGโ-23โ script has an unresolved tag ๐LG_BAD_MICS_DELAYโ-24โ bad MICS delay (too large) โฑ๏ธLG_BAD_MILS_DELAYโ-25โ bad MILS delay (too large) โฑ๏ธLG_I2C_OPEN_FAILEDโ-26โ can not open I2C device ๐LG_SERIAL_OPEN_FAILEDโ-27โ can not open serial device ๐LG_SPI_OPEN_FAILEDโ-28โ can not open SPI device ๐LG_BAD_I2C_BUSโ-29โ bad I2C bus ๐LG_BAD_I2C_ADDRโ-30โ bad I2C address ๐ฌLG_BAD_SPI_CHANNELโ-31โ bad SPI channel ๐บLG_BAD_I2C_FLAGSโ-32โ bad I2C open flags ๐ฉLG_BAD_SPI_FLAGSโ-33โ bad SPI open flags ๐ฉLG_BAD_SERIAL_FLAGSโ-34โ bad serial open flags ๐ฉLG_BAD_SPI_SPEEDโ-35โ bad SPI speed ๐๏ธLG_BAD_SERIAL_DEVICEโ-36โ bad serial device name ๐ท๏ธLG_BAD_SERIAL_SPEEDโ-37โ bad serial baud rate ๐ขLG_BAD_FILE_PARAMโ-38โ bad file parameter ๐LG_BAD_I2C_PARAMโ-39โ bad I2C parameter ๐งLG_BAD_SERIAL_PARAMโ-40โ bad serial parameter ๐งLG_I2C_WRITE_FAILEDโ-41โ i2c write failed โ๏ธLG_I2C_READ_FAILEDโ-42โ i2c read failed ๐LG_BAD_SPI_COUNTโ-43โ bad SPI count ๐ขLG_SERIAL_WRITE_FAILEDโ-44โ ser write failed โ๏ธLG_SERIAL_READ_FAILEDโ-45โ ser read failed ๐LG_SERIAL_READ_NO_DATAโ-46โ ser read no data available, she's ghosting ๐ตLG_UNKNOWN_COMMANDโ-47โ unknown command, never heard of her ๐LG_SPI_XFER_FAILEDโ-48โ spi xfer/read/write failed ๐ฐ๏ธLG_BAD_POINTERโ-49โ bad (NULL) pointer ๐ฏLG_MSG_TOOBIGโ-50โ socket/pipe message too big ๐LG_BAD_MALLOC_MODEโ-51โ bad memory allocation mode ๐งLG_TOO_MANY_SEGSโ-52โ too many I2C transaction segments โ๏ธLG_BAD_I2C_SEGโ-53โ an I2C transaction segment failed ๐LG_BAD_SMBUS_CMDโ-54โ SMBus command not supported by driver ๐LG_BAD_I2C_WLENโ-55โ bad I2C write length ๐LG_BAD_I2C_RLENโ-56โ bad I2C read length ๐LG_BAD_I2C_CMDโ-57โ bad I2C command โLG_FILE_OPEN_FAILEDโ-58โ file open failed ๐LG_BAD_FILE_MODEโ-59โ bad file mode ๐๏ธLG_BAD_FILE_FLAGโ-60โ bad file flag ๐ฉLG_BAD_FILE_READโ-61โ bad file read ๐LG_BAD_FILE_WRITEโ-62โ bad file write โ๏ธLG_FILE_NOT_ROPENโ-63โ file not open for read ๐LG_FILE_NOT_WOPENโ-64โ file not open for write ๐LG_BAD_FILE_SEEKโ-65โ bad file seek ๐LG_NO_FILE_MATCHโ-66โ no files match the pattern ๐ซฅLG_NO_FILE_ACCESSโ-67โ no permission to access the file ๐LG_FILE_IS_A_DIRโ-68โ file is a directory ๐ (not what you thought bestie)LG_BAD_SHELL_STATUSโ-69โ bad shell return status ๐LG_BAD_SCRIPT_NAMEโ-70โ bad script name ๐ท๏ธLG_CMD_INTERRUPTEDโ-71โ Python socket command interrupted โLG_BAD_EVENT_REQUESTโ-72โ bad event request ๐LG_BAD_GPIO_NUMBERโ-73โ bad GPIO number ๐ขLG_BAD_GROUP_SIZEโ-74โ bad group size ๐ฅLG_BAD_LINEINFO_IOCTLโ-75โ bad lineinfo IOCTL ๐๏ธLG_BAD_READโ-76โ bad GPIO read ๐LG_BAD_WRITEโ-77โ bad GPIO write โ๏ธLG_CANNOT_OPEN_CHIPโ-78โ can not open gpiochip ๐ชLG_GPIO_BUSYโ-79โ GPIO busy, she's booked and blessed ๐LG_GPIO_NOT_ALLOCATEDโ-80โ GPIO not allocated ๐ซฅLG_NOT_A_GPIOCHIPโ-81โ not a gpiochip ๐ซLG_NOT_ENOUGH_MEMORYโ-82โ not enough memory ๐ตLG_POLL_FAILEDโ-83โ GPIO poll failed ๐LG_TOO_MANY_GPIOSโ-84โ too many GPIO ๐ซLG_UNEGPECTED_ERRORโ-85โ unexpected error ๐ฑ (yes that's the actual spelling in the source, iykyk, no notes ๐)LG_BAD_PWM_MICROSโ-86โ bad PWM micros ๐LG_NOT_GROUP_LEADERโ-87โ GPIO not the group leader ๐ (main character only)LG_SPI_IOCTL_FAILEDโ-88โ SPI iOCTL failed ๐๏ธLG_BAD_GPIOCHIPโ-89โ bad gpiochip ๐งLG_BAD_CHIPINFO_IOCTLโ-90โ bad chipinfo IOCTL ๐๏ธLG_BAD_CONFIG_FILEโ-91โ bad configuration file โ๏ธLG_BAD_CONFIG_VALUEโ-92โ bad configuration value โ๏ธLG_NO_PERMISSIONSโ-93โ no permission to perform action ๐LG_BAD_USERNAMEโ-94โ bad user name ๐ท๏ธLG_BAD_SECRETโ-95โ bad secret for user ๐คซLG_TX_QUEUE_FULLโ-96โ TX queue full, she's overflowing ๐ฌLG_BAD_CONFIG_IDโ-97โ bad configuration id ๐ขLG_BAD_DEBOUNCE_MICSโ-98โ bad debounce microseconds ๐LG_BAD_WATCHDOG_MICSโ-99โ bad watchdog microseconds ๐LG_BAD_SERVO_FREQโ-100โ bad servo frequency ๐ปLG_BAD_SERVO_WIDTHโ-101โ bad servo pulsewidth ๐LG_BAD_PWM_FREQโ-102โ bad PWM frequency ๐ปLG_BAD_PWM_DUTYโ-103โ bad PWM dutycycle โ๏ธLG_GPIO_NOT_AN_OUTPUTโ-104โ GPIO not set as an output ๐คLG_INVALID_GROUP_ALERTโ-105โ can not set a group to alert ๐จ
๐ก pro tip bestie: when something returns one of these, it's negative, so < 0 means "check which one it is". The named constant is the whole point โ don't just stare at the raw number like it's a cryptic text from your ex ๐ซถ
๐ SEE ALSO ๐
go read these next, they're the friend group:
aaaand that's the whole page bestie, you made it to the end ๐๐ slay, go write some GPIO. this one's from the lgpio(3) man page on Linux, dated 2020-2021, and it's giving โจ documentation era โจ. mwah, go forth and blink an LED for me ๐ฆ๐ธ
๐ฆ where this page comes from
- ubuntu noble: liblgpio-dev 0.2.0.0-0ubuntu3 ยท LicenseRef-public-domain
- ubuntu questing: liblgpio-dev 0.2.0.0-0ubuntu4
- ubuntu resolute: liblgpio-dev 0.2.0.0-0ubuntu6 ยท LicenseRef-public-domain
- ubuntu stonking: liblgpio-dev 0.2.0.0-0ubuntu6 ยท LicenseRef-public-domain
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms