mirror of https://github.com/joan2937/pigpio
V10
This commit is contained in:
parent
a58a98d17b
commit
7f0cf5a014
|
@ -0,0 +1,47 @@
|
||||||
|
CC = gcc
|
||||||
|
AR = ar
|
||||||
|
RANLIB = ranlib
|
||||||
|
SIZE = size
|
||||||
|
|
||||||
|
CFLAGS = -O3 -Wall
|
||||||
|
|
||||||
|
ALL = libpigpiod_if.a pigs
|
||||||
|
|
||||||
|
all: $(ALL)
|
||||||
|
|
||||||
|
pigs: command.o
|
||||||
|
$(CC) -o pigs pigs.c command.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o *.i *.s *~ $(ALL)
|
||||||
|
|
||||||
|
install: $(LIB)
|
||||||
|
sudo install -m 0755 -d /usr/local/include
|
||||||
|
sudo install -m 0644 pigpio.h /usr/local/include
|
||||||
|
sudo install -m 0644 pigpiod_if.h /usr/local/include
|
||||||
|
sudo install -m 0755 -d /usr/local/lib
|
||||||
|
sudo install -m 0644 libpigpiod_if.a /usr/local/lib
|
||||||
|
sudo install -m 0755 -d /usr/local/bin
|
||||||
|
sudo install -m 0755 pigs /usr/local/bin
|
||||||
|
sudo python setup.py install
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
sudo rm -f /usr/local/include/pigpio.h
|
||||||
|
sudo rm -f /usr/local/lib/libpigpiod_if.a
|
||||||
|
sudo rm -f /usr/local/bin/pigs
|
||||||
|
|
||||||
|
LIB = libpigpiod_if.a
|
||||||
|
OBJ = pigpiod_if.o command.o
|
||||||
|
|
||||||
|
$(LIB): $(OBJ)
|
||||||
|
$(AR) rcs $(LIB) $(OBJ)
|
||||||
|
$(RANLIB) $(LIB)
|
||||||
|
$(SIZE) $(LIB)
|
||||||
|
|
||||||
|
# generated using gcc -MM *.c
|
||||||
|
|
||||||
|
command.o: command.c pigpio.h command.h
|
||||||
|
pigpiod.o: pigpiod.c pigpio.h command.h
|
||||||
|
pigpiod_if.o: pigpiod_if.c pigpio.h pigpiod_if.h
|
||||||
|
pigs.o: pigs.c pigpio.h command.h
|
||||||
|
|
51
Makefile
51
Makefile
|
@ -5,33 +5,42 @@ SIZE = size
|
||||||
|
|
||||||
CFLAGS = -O3 -Wall
|
CFLAGS = -O3 -Wall
|
||||||
|
|
||||||
ALL = libpigpio.a checklib demolib pig2vcd pigpiod pigs
|
LIB1 = libpigpio.a
|
||||||
|
OBJ1 = pigpio.o command.o
|
||||||
|
|
||||||
|
LIB2 = libpigpiod_if.a
|
||||||
|
OBJ2 = pigpiod_if.o command.o
|
||||||
|
|
||||||
|
LIB = $(LIB1) $(LIB2)
|
||||||
|
|
||||||
|
ALL = $(LIB) checklib pig2vcd pigpiod pigs
|
||||||
|
|
||||||
|
LL = -L. -lpigpio -lpthread -lrt
|
||||||
|
|
||||||
all: $(ALL)
|
all: $(ALL)
|
||||||
|
|
||||||
checklib: checklib.o libpigpio.a
|
checklib: checklib.o $(LIB1)
|
||||||
$(CC) -o checklib checklib.c -L. -lpigpio -lpthread -lrt
|
$(CC) -o checklib checklib.c $(LL)
|
||||||
|
|
||||||
demolib: demolib.o libpigpio.a
|
pigpiod: pigpiod.o $(LIB1)
|
||||||
$(CC) -o demolib demolib.c -L. -lpigpio -lpthread -lrt
|
$(CC) -o pigpiod pigpiod.c $(LL)
|
||||||
|
|
||||||
|
pigs: pigs.o command.o
|
||||||
|
$(CC) -o pigs pigs.c command.c
|
||||||
|
|
||||||
pig2vcd: pig2vcd.o
|
pig2vcd: pig2vcd.o
|
||||||
$(CC) -o pig2vcd pig2vcd.c
|
$(CC) -o pig2vcd pig2vcd.c
|
||||||
|
|
||||||
pigpiod: pigpiod.o libpigpio.a
|
|
||||||
$(CC) -o pigpiod pigpiod.c -L. -lpigpio -lpthread -lrt
|
|
||||||
|
|
||||||
pigs: command.o
|
|
||||||
$(CC) -o pigs pigs.c command.c
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.i *.s *~ $(ALL)
|
rm -f *.o *.i *.s *~ $(ALL)
|
||||||
|
|
||||||
install: $(LIB)
|
install: $(LIB)
|
||||||
sudo install -m 0755 -d /usr/local/include
|
sudo install -m 0755 -d /usr/local/include
|
||||||
sudo install -m 0644 pigpio.h /usr/local/include
|
sudo install -m 0644 pigpio.h /usr/local/include
|
||||||
|
sudo install -m 0644 pigpiod_if.h /usr/local/include
|
||||||
sudo install -m 0755 -d /usr/local/lib
|
sudo install -m 0755 -d /usr/local/lib
|
||||||
sudo install -m 0644 libpigpio.a /usr/local/lib
|
sudo install -m 0644 libpigpio.a /usr/local/lib
|
||||||
|
sudo install -m 0644 libpigpiod_if.a /usr/local/lib
|
||||||
sudo install -m 0755 -d /usr/local/bin
|
sudo install -m 0755 -d /usr/local/bin
|
||||||
sudo install -m 0755 pig2vcd /usr/local/bin
|
sudo install -m 0755 pig2vcd /usr/local/bin
|
||||||
sudo install -m 0755 pigpiod /usr/local/bin
|
sudo install -m 0755 pigpiod /usr/local/bin
|
||||||
|
@ -40,26 +49,30 @@ install: $(LIB)
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
sudo rm -f /usr/local/include/pigpio.h
|
sudo rm -f /usr/local/include/pigpio.h
|
||||||
|
sudo rm -f /usr/local/include/pigpiod_if.h
|
||||||
sudo rm -f /usr/local/lib/libpigpio.a
|
sudo rm -f /usr/local/lib/libpigpio.a
|
||||||
|
sudo rm -f /usr/local/lib/libpigpiod_if.a
|
||||||
sudo rm -f /usr/local/bin/pig2vcd
|
sudo rm -f /usr/local/bin/pig2vcd
|
||||||
sudo rm -f /usr/local/bin/pigpiod
|
sudo rm -f /usr/local/bin/pigpiod
|
||||||
sudo rm -f /usr/local/bin/pigs
|
sudo rm -f /usr/local/bin/pigs
|
||||||
|
|
||||||
LIB = libpigpio.a
|
$(LIB1): $(OBJ1)
|
||||||
OBJ = pigpio.o command.o
|
$(AR) rcs $(LIB1) $(OBJ1)
|
||||||
|
$(RANLIB) $(LIB1)
|
||||||
|
$(SIZE) $(LIB1)
|
||||||
|
|
||||||
$(LIB): $(OBJ)
|
$(LIB2): $(OBJ2)
|
||||||
$(AR) rcs $(LIB) $(OBJ)
|
$(AR) rcs $(LIB2) $(OBJ2)
|
||||||
$(RANLIB) $(LIB)
|
$(RANLIB) $(LIB2)
|
||||||
$(SIZE) $(LIB)
|
$(SIZE) $(LIB2)
|
||||||
|
|
||||||
# generated using gcc -M *.c
|
# generated using gcc -MM *.c
|
||||||
|
|
||||||
checklib.o: checklib.c pigpio.h
|
checklib.o: checklib.c pigpio.h
|
||||||
command.o: command.c pigpio.h command.h
|
command.o: command.c pigpio.h command.h
|
||||||
demolib.o: demolib.c pigpio.h
|
|
||||||
pig2vcd.o: pig2vcd.c pigpio.h
|
pig2vcd.o: pig2vcd.c pigpio.h
|
||||||
pigpio.o: pigpio.c pigpio.h command.h
|
pigpio.o: pigpio.c pigpio.h command.h
|
||||||
pigpiod.o: pigpiod.c pigpio.h command.h
|
pigpiod.o: pigpiod.c pigpio.h command.h
|
||||||
|
pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h
|
||||||
pigs.o: pigs.c pigpio.h command.h
|
pigs.o: pigs.c pigpio.h command.h
|
||||||
|
|
||||||
|
|
72
README
72
README
|
@ -9,13 +9,16 @@ Enter the following two commands (in this order)
|
||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
|
|
||||||
This will install:
|
This will install
|
||||||
the library (libpigpio.a) in /usr/local/lib
|
|
||||||
the header file (pigpio.h) in /usr/local/include
|
o the library (libpigpio.a) in /usr/local/lib
|
||||||
the daemon (pigpiod) in /usr/local/bin
|
o the library (libpigpiod_if.a) in /usr/local/lib
|
||||||
the socket interface (pigs) in /usr/local/bin
|
o the header file (pigpio.h) in /usr/local/include
|
||||||
the utility pig2vcd in /usr/local/bin
|
o the header file (pigpiod_if.h) in /usr/local/include
|
||||||
the Python module pigpio.py
|
o the daemon (pigpiod) in /usr/local/bin
|
||||||
|
o the socket interface (pigs) in /usr/local/bin
|
||||||
|
o the utility pig2vcd in /usr/local/bin
|
||||||
|
o the Python module pigpio.py
|
||||||
|
|
||||||
TEST
|
TEST
|
||||||
|
|
||||||
|
@ -23,8 +26,13 @@ To test the library do
|
||||||
|
|
||||||
sudo ./checklib
|
sudo ./checklib
|
||||||
|
|
||||||
checklib.c, demolib.c, pig2vcd.c, pigpiod.c, pigs.c, and pigpio.py
|
EXAMPLE CODE
|
||||||
show examples of interfacing with the library.
|
|
||||||
|
checklib.c, pig2vcd.c, and pigpiod.c
|
||||||
|
show examples of interfacing with the pigpio library.
|
||||||
|
|
||||||
|
pigs.c, pigpio.py, and test_pigpiod_if.c
|
||||||
|
show examples of interfacing with the pigpiod daemon.
|
||||||
|
|
||||||
DAEMON
|
DAEMON
|
||||||
|
|
||||||
|
@ -39,7 +47,7 @@ When the library starts it locks
|
||||||
|
|
||||||
/var/run/pigpio.pid
|
/var/run/pigpio.pid
|
||||||
|
|
||||||
The file should be deleted when the library terminates.
|
The file should be automatically deleted when the library terminates.
|
||||||
|
|
||||||
SOCKET INTERFACE
|
SOCKET INTERFACE
|
||||||
|
|
||||||
|
@ -62,16 +70,16 @@ echo "help" >/dev/pigpio
|
||||||
|
|
||||||
PYTHON MODULE
|
PYTHON MODULE
|
||||||
|
|
||||||
By default the Python pigpio module is installed to the
|
The Python pigpio module is installed to the default python location.
|
||||||
default python location. You can install it for additional
|
|
||||||
Python versions by
|
You can install it for additional Python versions by
|
||||||
|
|
||||||
pythonx.y setup.py install
|
pythonx.y setup.py install
|
||||||
|
|
||||||
where x.y is the Python version.
|
where x.y is the Python version.
|
||||||
|
|
||||||
If the pigpiod daemon is running you can test the Python
|
If the pigpiod daemon is running you can test the Python module
|
||||||
module by entering the following commands.
|
by entering the following commands.
|
||||||
|
|
||||||
python
|
python
|
||||||
|
|
||||||
|
@ -95,3 +103,37 @@ To stop the pigpiod daemon
|
||||||
|
|
||||||
sudo killall pigpiod
|
sudo killall pigpiod
|
||||||
|
|
||||||
|
RUNNING ON NON Pi's
|
||||||
|
|
||||||
|
You can access the pigpiod daemon running on the Pi from any machine which
|
||||||
|
can access it over the network. This access is via the socket interface.
|
||||||
|
|
||||||
|
In particular this allows you to use the following on non-Pi's.
|
||||||
|
|
||||||
|
o pigs
|
||||||
|
o the pigpio Python module
|
||||||
|
o the C socket I/F using libpigpiod_if (header file pigpiod_if.h)
|
||||||
|
|
||||||
|
On a Linux machine
|
||||||
|
|
||||||
|
make -f MakeRemote clean
|
||||||
|
make -f MakeRemote
|
||||||
|
make -f MakeRemote install
|
||||||
|
|
||||||
|
This will install
|
||||||
|
|
||||||
|
o the library (libpigpiod_if.a) in /usr/local/lib
|
||||||
|
o the header file (pigpio.h) in /usr/local/include
|
||||||
|
o the header file (pigpiod_if.h) in /usr/local/include
|
||||||
|
o the socket interface (pigs) in /usr/local/bin
|
||||||
|
o the Python module pigpio.py
|
||||||
|
|
||||||
|
On Windows machines (and possibly Macs)
|
||||||
|
|
||||||
|
The Python module should install with
|
||||||
|
|
||||||
|
python setup.py install
|
||||||
|
|
||||||
|
pigs and pigpiod_if.c will need minor mods to reflect the
|
||||||
|
Window's/Mac's socket interface.
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This version is for pigpio version 7+
|
This version is for pigpio version 10+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -74,6 +74,7 @@ cmdInfo_t cmdInfo[]=
|
||||||
{PI_CMD_TICK, "T", 1, 4},
|
{PI_CMD_TICK, "T", 1, 4},
|
||||||
{PI_CMD_HELP, "HELP", 6, 5},
|
{PI_CMD_HELP, "HELP", 6, 5},
|
||||||
{PI_CMD_HELP, "H", 6, 5},
|
{PI_CMD_HELP, "H", 6, 5},
|
||||||
|
{PI_CMD_PIGPV, "PIGPV", 1, 4},
|
||||||
};
|
};
|
||||||
|
|
||||||
char * cmdUsage = "\
|
char * cmdUsage = "\
|
||||||
|
@ -93,6 +94,7 @@ NC h close notification\n\
|
||||||
PWM/P u d set PWM value for gpio\n\
|
PWM/P u d set PWM value for gpio\n\
|
||||||
PFS u d set PWM frequency for gpio\n\
|
PFS u d set PWM frequency for gpio\n\
|
||||||
PFG u get PWM frequency for gpio\n\
|
PFG u get PWM frequency for gpio\n\
|
||||||
|
PIGPV return pigpio version\n\
|
||||||
PRS u d set PWM range for gpio\n\
|
PRS u d set PWM range for gpio\n\
|
||||||
PRG u get PWM range for gpio\n\
|
PRG u get PWM range for gpio\n\
|
||||||
PRRG u get PWM real range for gpio\n\
|
PRRG u get PWM real range for gpio\n\
|
||||||
|
@ -159,6 +161,8 @@ static errInfo_t errInfo[]=
|
||||||
{PI_TOO_MANY_PULSES , "waveform has too many pulses"},
|
{PI_TOO_MANY_PULSES , "waveform has too many pulses"},
|
||||||
{PI_TOO_MANY_CHARS , "waveform has too many chars"},
|
{PI_TOO_MANY_CHARS , "waveform has too many chars"},
|
||||||
{PI_NOT_SERIAL_GPIO , "no serial read in progress on gpio"},
|
{PI_NOT_SERIAL_GPIO , "no serial read in progress on gpio"},
|
||||||
|
{PI_BAD_SERIAL_STRUC , "bad (null) serial structure parameter"},
|
||||||
|
{PI_BAD_SERIAL_BUF , "bad (null) serial buf parameter"},
|
||||||
{PI_NOT_PERMITTED , "no permission to update gpio"},
|
{PI_NOT_PERMITTED , "no permission to update gpio"},
|
||||||
{PI_SOME_PERMITTED , "no permission to update one or more gpios"},
|
{PI_SOME_PERMITTED , "no permission to update one or more gpios"},
|
||||||
};
|
};
|
||||||
|
@ -200,7 +204,7 @@ int cmdParse(char * buf, cmdCmd_t * cmd)
|
||||||
|
|
||||||
switch (cmdInfo[idx].vt)
|
switch (cmdInfo[idx].vt)
|
||||||
{
|
{
|
||||||
case 1: /* BR1 BR2 HWVER NO TICK */
|
case 1: /* BR1 BR2 HWVER PIGPV NO TICK */
|
||||||
f = sscanf(buf, " %7s %c", str, &t);
|
f = sscanf(buf, " %7s %c", str, &t);
|
||||||
if (f == 1) valid = 1;
|
if (f == 1) valid = 1;
|
||||||
break;
|
break;
|
||||||
|
|
673
demolib.c
673
demolib.c
|
@ -1,673 +0,0 @@
|
||||||
/*
|
|
||||||
This is free and unencumbered software released into the public domain.
|
|
||||||
|
|
||||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
||||||
distribute this software, either in source code form or as a compiled
|
|
||||||
binary, for any purpose, commercial or non-commercial, and by any
|
|
||||||
means.
|
|
||||||
|
|
||||||
In jurisdictions that recognize copyright laws, the author or authors
|
|
||||||
of this software dedicate any and all copyright interest in the
|
|
||||||
software to the public domain. We make this dedication for the benefit
|
|
||||||
of the public at large and to the detriment of our heirs and
|
|
||||||
successors. We intend this dedication to be an overt act of
|
|
||||||
relinquishment in perpetuity of all present and future rights to this
|
|
||||||
software under copyright law.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
||||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
For more information, please refer to <http://unlicense.org/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
This version is for pigpio version 3+
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <linux/i2c-dev.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
#include "pigpio.h"
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
THIS PROGRAM NEEDS THE I2C DEVICE AND DEVELOPMENT LIBRARY
|
|
||||||
|
|
||||||
TO GET THE NEEDED FILES DO
|
|
||||||
|
|
||||||
sudo apt-get install libi2c-dev
|
|
||||||
|
|
||||||
BEFORE RUNNING THE PROGRAM ENSURE THAT THE I2C DEVICE IS PRESENT
|
|
||||||
|
|
||||||
sudo modprobe i2c-bcm2708
|
|
||||||
sudo modprobe i2c-dev
|
|
||||||
sudo chmod o+rw /dev/i2c*
|
|
||||||
=========================================================================== */
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
P1 Name gpio used for
|
|
||||||
|
|
||||||
3 SDA 0/2 i2c
|
|
||||||
5 SCL 1/3 i2c
|
|
||||||
7 --- 4 LASER
|
|
||||||
8 TXD 14 LED1
|
|
||||||
10 RXD 15 LED2
|
|
||||||
11 --- 17 SERVO 1
|
|
||||||
12 --- 18 SERVO 2
|
|
||||||
13 --- 21/27 SERVO 3
|
|
||||||
15 --- 22 LED3
|
|
||||||
16 --- 23 TI Launchpad
|
|
||||||
18 --- 24 Sonar trigger
|
|
||||||
19 MOSI 10 Sonar echo
|
|
||||||
21 MISO 9 Motor B In 1
|
|
||||||
22 --- 25 LDR
|
|
||||||
23 SCLK 11 Motor B In 2
|
|
||||||
24 CE0 8 Motor A In1
|
|
||||||
26 CE1 7 Motor A In2
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define LASER 4
|
|
||||||
#define MOTOR_A_IN2 7
|
|
||||||
#define MOTOR_A_IN1 8
|
|
||||||
#define MOTOR_B_IN1 9
|
|
||||||
#define SONAR_ECHO 10
|
|
||||||
#define MOTOR_B_IN2 11
|
|
||||||
#define LED1 14
|
|
||||||
#define LED2 15
|
|
||||||
#define SERVO1 17
|
|
||||||
#define SERVO2 18
|
|
||||||
#define SERVO3 21
|
|
||||||
#define LED3 22
|
|
||||||
#define LAUNCHPAD 23
|
|
||||||
#define SONAR_TRIGGER 24
|
|
||||||
#define LDR 25
|
|
||||||
|
|
||||||
#define LEDS 4
|
|
||||||
|
|
||||||
short rawAcc[3];
|
|
||||||
short rawGyr[3];
|
|
||||||
short rawMag[3];
|
|
||||||
|
|
||||||
#define ROLL 0
|
|
||||||
#define PITCH 1
|
|
||||||
#define YAW 2
|
|
||||||
|
|
||||||
#define ACC_ORIENTATION(X, Y, Z) \
|
|
||||||
{rawAcc[ROLL] = -X; rawAcc[PITCH] = -Y; rawAcc[YAW] = Z;}
|
|
||||||
|
|
||||||
#define GYRO_ORIENTATION(X, Y, Z) \
|
|
||||||
{rawGyr[ROLL] = Y; rawGyr[PITCH] = -X; rawGyr[YAW] = -Z;}
|
|
||||||
|
|
||||||
#define MAG_ORIENTATION(X, Y, Z) \
|
|
||||||
{rawMag[ROLL] = X; rawMag[PITCH] = Y; rawMag[YAW] = -Z;}
|
|
||||||
|
|
||||||
|
|
||||||
#define CALIBRATIONS 200
|
|
||||||
|
|
||||||
#define ADXL345_I2C_ADDR 0x53
|
|
||||||
#define ITG3200_I2C_ADDR 0x68
|
|
||||||
|
|
||||||
static int version, micros=5, millis=100;
|
|
||||||
|
|
||||||
static volatile unsigned long launchpadPulses;
|
|
||||||
static volatile unsigned long launchpad5;
|
|
||||||
static volatile unsigned long launchpad10;
|
|
||||||
static volatile unsigned long launchpad15;
|
|
||||||
static volatile unsigned long launchpadOutRange;
|
|
||||||
static volatile int launchpadErr;
|
|
||||||
static volatile uint32_t LDRrechargeTick;
|
|
||||||
|
|
||||||
|
|
||||||
/* forward prototypes */
|
|
||||||
|
|
||||||
void LEDlaserTick (void);
|
|
||||||
void motorTick(void);
|
|
||||||
void i2cTick (void);
|
|
||||||
void servoTick (void);
|
|
||||||
void sonarLDRtick(void);
|
|
||||||
|
|
||||||
void launchpadAlert(int gpio, int level, uint32_t tick);
|
|
||||||
void sonarAlert(int gpio, int level, uint32_t tick);
|
|
||||||
void LDRalert(int gpio, int level, uint32_t tick);
|
|
||||||
|
|
||||||
void putTTY(char * buf);
|
|
||||||
void putTTYstr(int row, int col, char * buf);
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
char str[256];
|
|
||||||
|
|
||||||
if (argc > 1) micros = atoi(argv[1]);
|
|
||||||
|
|
||||||
if (argc > 2) millis = atoi(argv[2]);
|
|
||||||
|
|
||||||
putTTY("\033c"); /* clear console */
|
|
||||||
|
|
||||||
gpioCfgBufferSize(millis);
|
|
||||||
|
|
||||||
gpioCfgClock(micros, PI_CLOCK_PCM, PI_CLOCK_PLLD);
|
|
||||||
|
|
||||||
|
|
||||||
/* before using the library you must call gpioInitialise */
|
|
||||||
|
|
||||||
version = gpioInitialise();
|
|
||||||
|
|
||||||
if (version >= 0)
|
|
||||||
{
|
|
||||||
/* initialise pins, only gpio numbers are supported */
|
|
||||||
|
|
||||||
gpioSetMode(SERVO1, PI_OUTPUT);
|
|
||||||
gpioSetMode(SERVO2, PI_OUTPUT);
|
|
||||||
gpioSetMode(SERVO3, PI_OUTPUT);
|
|
||||||
gpioSetMode(LASER, PI_OUTPUT);
|
|
||||||
gpioSetMode(LED1, PI_OUTPUT);
|
|
||||||
gpioSetMode(LED2, PI_OUTPUT);
|
|
||||||
gpioSetMode(LED3, PI_OUTPUT);
|
|
||||||
gpioSetMode(MOTOR_A_IN1, PI_OUTPUT);
|
|
||||||
gpioSetMode(MOTOR_A_IN2, PI_OUTPUT);
|
|
||||||
gpioSetMode(MOTOR_B_IN1, PI_OUTPUT);
|
|
||||||
gpioSetMode(MOTOR_B_IN2, PI_OUTPUT);
|
|
||||||
|
|
||||||
gpioSetMode(SONAR_TRIGGER, PI_OUTPUT);
|
|
||||||
gpioWrite (SONAR_TRIGGER, PI_OFF);
|
|
||||||
|
|
||||||
gpioSetMode(SONAR_ECHO, PI_INPUT);
|
|
||||||
gpioSetMode(LAUNCHPAD, PI_INPUT);
|
|
||||||
gpioSetMode(LDR, PI_INPUT);
|
|
||||||
|
|
||||||
/* update i2c fifty times a second, timer #0 */
|
|
||||||
|
|
||||||
gpioSetTimerFunc(0, 20, i2cTick);
|
|
||||||
|
|
||||||
//gpioSetTimerFunc(0, 1000, servoTick);
|
|
||||||
|
|
||||||
/* update LEDs and laser once a second, timer #1 */
|
|
||||||
|
|
||||||
gpioSetTimerFunc(1, 1000, LEDlaserTick);
|
|
||||||
|
|
||||||
/* update motors every three seconds, timer #2 */
|
|
||||||
|
|
||||||
gpioSetTimerFunc(2, 3000, motorTick);
|
|
||||||
|
|
||||||
/* update sonar/LDR 10 times a second, timer #3 */
|
|
||||||
|
|
||||||
gpioSetTimerFunc(3, 100, sonarLDRtick);
|
|
||||||
|
|
||||||
/* an attachecd TI launchpad is transmitting high pulses of
|
|
||||||
15, 35, 55, 75, ..., 975, 995 microseconds repeating with 50
|
|
||||||
microseconds off between each pulse */
|
|
||||||
|
|
||||||
gpioSetAlertFunc(LAUNCHPAD, launchpadAlert);
|
|
||||||
|
|
||||||
/* monitor sonar echos */
|
|
||||||
|
|
||||||
gpioSetAlertFunc(SONAR_ECHO, sonarAlert);
|
|
||||||
|
|
||||||
/* monitor LDR level changes */
|
|
||||||
|
|
||||||
gpioSetAlertFunc(LDR, LDRalert);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
sprintf(str, "TI pulses %8ld", launchpadPulses);
|
|
||||||
putTTYstr(9, 1, str);
|
|
||||||
|
|
||||||
sprintf(str, "+/-5 %8ld", launchpad5);
|
|
||||||
putTTYstr(10, 6, str);
|
|
||||||
|
|
||||||
sprintf(str, "+/-10 %8ld", launchpad10);
|
|
||||||
putTTYstr(11, 5, str);
|
|
||||||
|
|
||||||
sprintf(str, "+/-15 %8ld", launchpad15);
|
|
||||||
putTTYstr(12, 5, str);
|
|
||||||
|
|
||||||
sprintf(str, "Others %8ld (last %d) ",
|
|
||||||
launchpadOutRange, launchpadErr);
|
|
||||||
putTTYstr(13, 4, str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gpioTerminate();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LEDlaserTick(void)
|
|
||||||
{
|
|
||||||
static int gpio[LEDS]={LED1, LED2, LED3, LASER};
|
|
||||||
static int pos [LEDS]={ 0, 3, 6, 9};
|
|
||||||
static int inc [LEDS]={ 1, 1, 1, 1};
|
|
||||||
|
|
||||||
static int vals[] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 249};
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i<LEDS; i++)
|
|
||||||
{
|
|
||||||
gpioPWM(gpio[i], vals[pos[i]]);
|
|
||||||
|
|
||||||
pos[i] += inc[i];
|
|
||||||
|
|
||||||
if ( (pos[i]>=(sizeof(vals)/4)) || (pos[i]<0) )
|
|
||||||
{
|
|
||||||
inc[i] = -inc[i];
|
|
||||||
pos[i] += inc[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sonarLDRtick(void)
|
|
||||||
{
|
|
||||||
/* trigger a sonar reading */
|
|
||||||
|
|
||||||
gpioWrite(SONAR_TRIGGER, PI_ON);
|
|
||||||
usleep(20);
|
|
||||||
gpioWrite(SONAR_TRIGGER, PI_OFF);
|
|
||||||
|
|
||||||
/* trigger a LDR reading */
|
|
||||||
|
|
||||||
gpioSetMode(LDR, PI_OUTPUT); /* drain capacitor */
|
|
||||||
|
|
||||||
gpioWrite(LDR, PI_OFF);
|
|
||||||
|
|
||||||
usleep(200);
|
|
||||||
|
|
||||||
LDRrechargeTick = gpioTick();
|
|
||||||
|
|
||||||
gpioSetMode(LDR, PI_INPUT); /* start capacitor recharge */
|
|
||||||
}
|
|
||||||
|
|
||||||
void motorTick(void)
|
|
||||||
{
|
|
||||||
static int gpio_in1[2]={MOTOR_A_IN1, MOTOR_B_IN1};
|
|
||||||
static int gpio_in2[2]={MOTOR_A_IN2, MOTOR_B_IN2};
|
|
||||||
static int speed [2]={ 80, 80};
|
|
||||||
static int inc [2]={ -50, 50};
|
|
||||||
|
|
||||||
int i;
|
|
||||||
char str[256];
|
|
||||||
|
|
||||||
for (i=0; i<2; i++)
|
|
||||||
{
|
|
||||||
speed[i]+=inc[i];
|
|
||||||
|
|
||||||
if (speed[i]<0)
|
|
||||||
{
|
|
||||||
gpioPWM(gpio_in1[i], -speed[i]);
|
|
||||||
gpioPWM(gpio_in2[i], 0);
|
|
||||||
if (speed[i] < -205) inc[i] = -inc[i];
|
|
||||||
sprintf(str, "MOT%d IN1=%3d IN2=%3d", i+1, -speed[i], 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gpioPWM(gpio_in2[i], speed[i]);
|
|
||||||
gpioPWM(gpio_in1[i], 0);
|
|
||||||
if (speed[i] > 205) inc[i] = -inc[i];
|
|
||||||
sprintf(str, "MOT%d IN1=%3d IN2=%3d", i+1, 0, speed[i]);
|
|
||||||
}
|
|
||||||
if (i) putTTYstr(7, 1, str); else putTTYstr(5, 1, str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* loads of code to read/write i2c */
|
|
||||||
|
|
||||||
void selectDevice(int i2c, int addr, char * name)
|
|
||||||
{
|
|
||||||
if (ioctl(i2c, I2C_SLAVE, addr) < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s not present\n", name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeToDevice(int i2c, char * buf, int len)
|
|
||||||
{
|
|
||||||
static int reported = 0;
|
|
||||||
if (write(i2c, buf, len) != len)
|
|
||||||
{
|
|
||||||
if (!reported)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Can't write to device\n");
|
|
||||||
reported = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else reported = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void readADXL345(int i2c)
|
|
||||||
{
|
|
||||||
char buf[8];
|
|
||||||
static int reported = 0;
|
|
||||||
|
|
||||||
selectDevice(i2c, ADXL345_I2C_ADDR, "ADXL345");
|
|
||||||
|
|
||||||
writeToDevice(i2c, "\x32", 1);
|
|
||||||
|
|
||||||
if (read(i2c, buf, 6) != 6)
|
|
||||||
{
|
|
||||||
if (!reported)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Unable to read from ADXL345\n");
|
|
||||||
reported = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reported = 0;
|
|
||||||
|
|
||||||
ACC_ORIENTATION (
|
|
||||||
((buf[1]<<8) | buf[0]),
|
|
||||||
((buf[3]<<8) | buf[2]),
|
|
||||||
((buf[5]<<8) | buf[4]) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void readITG3200(int i2c)
|
|
||||||
{
|
|
||||||
char buf[8];
|
|
||||||
static int reported = 0;
|
|
||||||
|
|
||||||
selectDevice(i2c, ITG3200_I2C_ADDR, "ITG3200");
|
|
||||||
|
|
||||||
writeToDevice(i2c, "\x1D", 1);
|
|
||||||
|
|
||||||
if (read(i2c, buf, 6) != 6)
|
|
||||||
{
|
|
||||||
if (!reported)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Unable to read from ITG3200\n");
|
|
||||||
reported = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reported = 0;
|
|
||||||
|
|
||||||
GYRO_ORIENTATION (
|
|
||||||
((buf[0]<<8) | buf[1]),
|
|
||||||
((buf[2]<<8) | buf[3]),
|
|
||||||
((buf[4]<<8) | buf[5]) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int initI2Cdevices(void)
|
|
||||||
{
|
|
||||||
int i2c;
|
|
||||||
|
|
||||||
if ((i2c = open("/dev/i2c-0", O_RDWR)) < 0)
|
|
||||||
{
|
|
||||||
perror("Failed to open i2c bus");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialise ADXL345 */
|
|
||||||
|
|
||||||
selectDevice(i2c, ADXL345_I2C_ADDR, "ADXL345");
|
|
||||||
|
|
||||||
writeToDevice(i2c, "\x2d\x00", 2);
|
|
||||||
writeToDevice(i2c, "\x2d\x10", 2);
|
|
||||||
writeToDevice(i2c, "\x2d\x08", 2);
|
|
||||||
writeToDevice(i2c, "\x31\x00", 2);
|
|
||||||
writeToDevice(i2c, "\x31\x0b", 2);
|
|
||||||
|
|
||||||
/* initialise ITG3200 */
|
|
||||||
|
|
||||||
selectDevice(i2c, ITG3200_I2C_ADDR, "ITG3200");
|
|
||||||
|
|
||||||
writeToDevice(i2c, "\x16\b00011000", 2);
|
|
||||||
|
|
||||||
return i2c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* an attached IMU (GY-85) supplies orientation information which
|
|
||||||
is used to position the servos */
|
|
||||||
|
|
||||||
float estimateAngle(int acc, int gyro, float oldAng, int elapsed)
|
|
||||||
{
|
|
||||||
float angleAcc, angleInc, estAngle;
|
|
||||||
float secs;
|
|
||||||
|
|
||||||
secs = (float) elapsed / 1e6f;
|
|
||||||
|
|
||||||
angleAcc = (float) acc * 90.0f / 256.0f;
|
|
||||||
|
|
||||||
angleInc = (float) gyro * secs * 2000.0f / 32768.0f;
|
|
||||||
|
|
||||||
estAngle = 0.75 * (oldAng + angleInc) + 0.25 * angleAcc;
|
|
||||||
|
|
||||||
return estAngle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void servoTick(void)
|
|
||||||
{
|
|
||||||
static int wid1=1500, wid2=1500, wid3=1500;
|
|
||||||
static int inc1=50, inc2=75, inc3=100;
|
|
||||||
|
|
||||||
gpioServo(SERVO1, wid1);
|
|
||||||
gpioServo(SERVO2, wid2);
|
|
||||||
gpioServo(SERVO3, wid3);
|
|
||||||
|
|
||||||
wid1+=inc1; if ((wid1<1000) || (wid1>2000)) {inc1 = -inc1; wid1+=inc1;}
|
|
||||||
wid2+=inc2; if ((wid2<1000) || (wid2>2000)) {inc2 = -inc2; wid2+=inc2;}
|
|
||||||
wid3+=inc3; if ((wid3<1000) || (wid3>2000)) {inc3 = -inc3; wid3+=inc3;}
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2cTick(void)
|
|
||||||
{
|
|
||||||
static int inited = 0;
|
|
||||||
static int calibrated = 0;
|
|
||||||
static int calibrations = 0;
|
|
||||||
static int accCalibX = 0, accCalibY = 0, accCalibZ = 0;
|
|
||||||
static int gyroCalibX = 0, gyroCalibY = 0, gyroCalibZ = 0;
|
|
||||||
static int i2c;
|
|
||||||
static float X=0.0, Y=0.0, Z=0.0;
|
|
||||||
|
|
||||||
static uint32_t lastTick;
|
|
||||||
|
|
||||||
uint32_t tick;
|
|
||||||
int elapsed;
|
|
||||||
int pulse;
|
|
||||||
char str[256];
|
|
||||||
|
|
||||||
if (inited)
|
|
||||||
{
|
|
||||||
tick = gpioTick();
|
|
||||||
elapsed = tick - lastTick;
|
|
||||||
lastTick = tick;
|
|
||||||
|
|
||||||
readADXL345(i2c);
|
|
||||||
readITG3200(i2c);
|
|
||||||
|
|
||||||
if (calibrated)
|
|
||||||
{
|
|
||||||
X = estimateAngle(
|
|
||||||
rawAcc[ROLL], rawGyr[ROLL] -gyroCalibX, X, elapsed);
|
|
||||||
|
|
||||||
Y = estimateAngle(
|
|
||||||
rawAcc[PITCH], rawGyr[PITCH] - gyroCalibY, Y, elapsed);
|
|
||||||
|
|
||||||
Z = estimateAngle(
|
|
||||||
rawAcc[YAW], rawGyr[YAW] - gyroCalibZ, Z, elapsed);
|
|
||||||
|
|
||||||
pulse = 1500 + (Y * 1000 / 90);
|
|
||||||
if (pulse < 500) pulse = 500;
|
|
||||||
if (pulse > 2500) pulse = 2500;
|
|
||||||
gpioServo(SERVO1, pulse);
|
|
||||||
|
|
||||||
pulse = 1500 - (X * 500 / 90);
|
|
||||||
if (pulse < 1000) pulse = 1000;
|
|
||||||
if (pulse > 2000) pulse = 2000;
|
|
||||||
gpioServo(SERVO2, pulse);
|
|
||||||
|
|
||||||
/* prefer Z but that doesn't change much */
|
|
||||||
pulse = 1500 - (Y * 500 / 90);
|
|
||||||
if (pulse < 800) pulse = 800;
|
|
||||||
if (pulse > 2200) pulse = 2200;
|
|
||||||
gpioServo(SERVO3, pulse);
|
|
||||||
|
|
||||||
sprintf(str, "X=%4.0f Y=%4.0f Z=%4.0f ", X, Y, Z);
|
|
||||||
putTTYstr(1, 1, str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
accCalibX+=rawAcc[ROLL];
|
|
||||||
accCalibY+=rawAcc[PITCH];
|
|
||||||
accCalibZ+=rawAcc[YAW];
|
|
||||||
|
|
||||||
gyroCalibX+=rawGyr[ROLL];
|
|
||||||
gyroCalibY+=rawGyr[PITCH];
|
|
||||||
gyroCalibZ+=rawGyr[YAW];
|
|
||||||
|
|
||||||
if (++calibrations >= CALIBRATIONS)
|
|
||||||
{
|
|
||||||
accCalibX /= CALIBRATIONS;
|
|
||||||
accCalibY /= CALIBRATIONS;
|
|
||||||
accCalibZ /= CALIBRATIONS;
|
|
||||||
|
|
||||||
gyroCalibX /= CALIBRATIONS;
|
|
||||||
gyroCalibY /= CALIBRATIONS;
|
|
||||||
gyroCalibZ /= CALIBRATIONS;
|
|
||||||
|
|
||||||
calibrated = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i2c = initI2Cdevices();
|
|
||||||
|
|
||||||
gpioServo(SERVO1, 1500);
|
|
||||||
gpioServo(SERVO2, 1500);
|
|
||||||
gpioServo(SERVO3, 1500);
|
|
||||||
|
|
||||||
inited = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sonarAlert(int gpio, int level, uint32_t tick)
|
|
||||||
{
|
|
||||||
static uint32_t startTick;
|
|
||||||
|
|
||||||
int diffTick;
|
|
||||||
char str[256];
|
|
||||||
|
|
||||||
if (level == PI_ON)
|
|
||||||
{
|
|
||||||
startTick = tick;
|
|
||||||
}
|
|
||||||
else if (level == PI_OFF)
|
|
||||||
{
|
|
||||||
diffTick = tick - startTick;
|
|
||||||
|
|
||||||
if (diffTick < 26100)
|
|
||||||
{
|
|
||||||
sprintf(str, "Sonar %3d cms", (diffTick+29)/58);
|
|
||||||
putTTYstr(15, 1, str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LDRalert(int pin, int level, uint32_t tick)
|
|
||||||
{
|
|
||||||
int diffTick;
|
|
||||||
char str[256];
|
|
||||||
|
|
||||||
if (level == PI_ON)
|
|
||||||
{
|
|
||||||
diffTick = tick - LDRrechargeTick;
|
|
||||||
|
|
||||||
sprintf(str, "LDR %4d micros", diffTick);
|
|
||||||
putTTYstr(17, 1, str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void launchpadAlert(int pin, int level, uint32_t tick)
|
|
||||||
{
|
|
||||||
static int inited = 0, lastTick, lastPulseLen;
|
|
||||||
|
|
||||||
int pulseLen, pulseDif;
|
|
||||||
|
|
||||||
if (inited)
|
|
||||||
{
|
|
||||||
pulseLen = tick - lastTick;
|
|
||||||
lastTick = tick;
|
|
||||||
|
|
||||||
if (level==0)
|
|
||||||
{
|
|
||||||
if (lastPulseLen)
|
|
||||||
{
|
|
||||||
pulseDif = pulseLen - lastPulseLen;
|
|
||||||
|
|
||||||
/* allow for wrap around */
|
|
||||||
if (pulseDif < 0) pulseDif += 1096;
|
|
||||||
|
|
||||||
/* now centre around expected value */
|
|
||||||
pulseDif -= 33;
|
|
||||||
|
|
||||||
if (pulseDif < 0) pulseDif = -pulseDif;
|
|
||||||
|
|
||||||
launchpadPulses++;
|
|
||||||
|
|
||||||
if (pulseDif <= 5)
|
|
||||||
{
|
|
||||||
launchpad5++;
|
|
||||||
}
|
|
||||||
else if (pulseDif <= 10)
|
|
||||||
{
|
|
||||||
launchpad10++;
|
|
||||||
}
|
|
||||||
else if (pulseDif <= 15)
|
|
||||||
{
|
|
||||||
launchpad15++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
launchpadOutRange++;
|
|
||||||
launchpadErr = pulseDif;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastPulseLen = pulseLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastTick = tick;
|
|
||||||
lastPulseLen = 0;
|
|
||||||
|
|
||||||
launchpadPulses = 0;
|
|
||||||
launchpad5 = 0;
|
|
||||||
launchpad10 = 0;
|
|
||||||
launchpad15 = 0;
|
|
||||||
launchpadOutRange = 0;
|
|
||||||
|
|
||||||
inited = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void putTTY(char * buf)
|
|
||||||
{
|
|
||||||
write(1, buf, strlen(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
void putTTYstr(int row, int col, char * buf)
|
|
||||||
{
|
|
||||||
char str[256];
|
|
||||||
|
|
||||||
sprintf(str, "\033[%d;%dH%s", row, col, buf);
|
|
||||||
|
|
||||||
putTTY(str);
|
|
||||||
}
|
|
||||||
|
|
112
pigpio.c
112
pigpio.c
|
@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
|
||||||
For more information, please refer to <http://unlicense.org/>
|
For more information, please refer to <http://unlicense.org/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* pigpio version 9 */
|
/* pigpio version 10 */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -198,6 +198,31 @@ bit 0 READ_LAST_NOT_SET_ERROR
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
|
#define CHECK_INITED_RET_NULL_PTR \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (!libInitialised) \
|
||||||
|
{ \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"%s %s: pigpio uninitialised, call gpioInitialise()\n",\
|
||||||
|
myTimeStamp(), __FUNCTION__); \
|
||||||
|
return (NULL); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define CHECK_INITED_RET_NIL \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (!libInitialised) \
|
||||||
|
{ \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"%s %s: pigpio uninitialised, call gpioInitialise()\n",\
|
||||||
|
myTimeStamp(), __FUNCTION__); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
#define CHECK_NOT_INITED \
|
#define CHECK_NOT_INITED \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
|
@ -981,7 +1006,8 @@ static void myDoCommand(cmdCmd_t * cmd)
|
||||||
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPullUpDown(p1, p2);
|
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPullUpDown(p1, p2);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PERM_ERROR("gpioSetPullUpDown: gpio %d, no permission to update", p1);
|
PERM_ERROR(
|
||||||
|
"gpioSetPullUpDown: gpio %d, no permission to update", p1);
|
||||||
res = PI_NOT_PERMITTED;
|
res = PI_NOT_PERMITTED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1012,7 +1038,8 @@ static void myDoCommand(cmdCmd_t * cmd)
|
||||||
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMrange(p1, p2);
|
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMrange(p1, p2);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PERM_ERROR("gpioSetPWMrange: gpio %d, no permission to update", p1);
|
PERM_ERROR(
|
||||||
|
"gpioSetPWMrange: gpio %d, no permission to update", p1);
|
||||||
res = PI_NOT_PERMITTED;
|
res = PI_NOT_PERMITTED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1021,7 +1048,8 @@ static void myDoCommand(cmdCmd_t * cmd)
|
||||||
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMfrequency(p1, p2);
|
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMfrequency(p1, p2);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PERM_ERROR("gpioSetPWMfrequency: gpio %d, no permission to update", p1);
|
PERM_ERROR(
|
||||||
|
"gpioSetPWMfrequency: gpio %d, no permission to update", p1);
|
||||||
res = PI_NOT_PERMITTED;
|
res = PI_NOT_PERMITTED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1054,7 +1082,8 @@ static void myDoCommand(cmdCmd_t * cmd)
|
||||||
|
|
||||||
if ((mask | p1) != mask)
|
if ((mask | p1) != mask)
|
||||||
{
|
{
|
||||||
PERM_ERROR("gpioWrite_Bits_0_31_Clear: bad levels %08X (permissions %08X)",
|
PERM_ERROR(
|
||||||
|
"gpioWrite_Bits_0_31_Clear: bad levels %08X (permissions %08X)",
|
||||||
p1, mask);
|
p1, mask);
|
||||||
res = PI_SOME_PERMITTED;
|
res = PI_SOME_PERMITTED;
|
||||||
}
|
}
|
||||||
|
@ -1067,7 +1096,8 @@ static void myDoCommand(cmdCmd_t * cmd)
|
||||||
|
|
||||||
if ((mask | p1) != mask)
|
if ((mask | p1) != mask)
|
||||||
{
|
{
|
||||||
PERM_ERROR("gpioWrite_Bits_32_53_Clear: bad levels %08X (permissions %08X)",
|
PERM_ERROR(
|
||||||
|
"gpioWrite_Bits_32_53_Clear: bad levels %08X (permissions %08X)",
|
||||||
p1, mask);
|
p1, mask);
|
||||||
res = PI_SOME_PERMITTED;
|
res = PI_SOME_PERMITTED;
|
||||||
}
|
}
|
||||||
|
@ -1080,7 +1110,8 @@ static void myDoCommand(cmdCmd_t * cmd)
|
||||||
|
|
||||||
if ((mask | p1) != mask)
|
if ((mask | p1) != mask)
|
||||||
{
|
{
|
||||||
PERM_ERROR("gpioWrite_Bits_0_31_Set: bad levels %08X (permissions %08X)",
|
PERM_ERROR(
|
||||||
|
"gpioWrite_Bits_0_31_Set: bad levels %08X (permissions %08X)",
|
||||||
p1, mask);
|
p1, mask);
|
||||||
res = PI_SOME_PERMITTED;
|
res = PI_SOME_PERMITTED;
|
||||||
}
|
}
|
||||||
|
@ -1093,7 +1124,8 @@ static void myDoCommand(cmdCmd_t * cmd)
|
||||||
|
|
||||||
if ((mask | p1) != mask)
|
if ((mask | p1) != mask)
|
||||||
{
|
{
|
||||||
PERM_ERROR("gpioWrite_Bits_32_53_Set: bad levels %08X (permissions %08X)",
|
PERM_ERROR(
|
||||||
|
"gpioWrite_Bits_32_53_Set: bad levels %08X (permissions %08X)",
|
||||||
p1, mask);
|
p1, mask);
|
||||||
res = PI_SOME_PERMITTED;
|
res = PI_SOME_PERMITTED;
|
||||||
}
|
}
|
||||||
|
@ -1138,6 +1170,10 @@ static void myDoCommand(cmdCmd_t * cmd)
|
||||||
case PI_CMD_HELP:
|
case PI_CMD_HELP:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PI_CMD_PIGPV:
|
||||||
|
res = gpioVersion();
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd->res = res;
|
cmd->res = res;
|
||||||
|
@ -4731,6 +4767,56 @@ int gpioSetTimerFuncEx(unsigned id, unsigned ms, gpioTimerFuncEx_t f,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
pthread_t *gpioStartThread(ThreadFunc_t func, void *arg)
|
||||||
|
{
|
||||||
|
pthread_t *pth;
|
||||||
|
pthread_attr_t pthAttr;
|
||||||
|
|
||||||
|
DBG(DBG_USER, "func=%08X, arg=%08X", (uint32_t)func, (uint32_t)arg);
|
||||||
|
|
||||||
|
CHECK_INITED_RET_NULL_PTR;
|
||||||
|
|
||||||
|
pth = malloc(sizeof(pthread_t));
|
||||||
|
|
||||||
|
if (pth)
|
||||||
|
{
|
||||||
|
if (pthread_attr_init(&pthAttr))
|
||||||
|
{
|
||||||
|
free(pth);
|
||||||
|
SOFT_ERROR(NULL, "pthread_attr_init failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_attr_setstacksize(&pthAttr, STACK_SIZE))
|
||||||
|
{
|
||||||
|
free(pth);
|
||||||
|
SOFT_ERROR(NULL, "pthread_attr_setstacksize failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_create(pth, &pthAttr, func, arg))
|
||||||
|
{
|
||||||
|
free(pth);
|
||||||
|
SOFT_ERROR(NULL, "pthread_create failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void gpioStopThread(pthread_t *pth)
|
||||||
|
{
|
||||||
|
DBG(DBG_USER, "pth=%08X", (uint32_t)pth);
|
||||||
|
|
||||||
|
CHECK_INITED_RET_NIL;
|
||||||
|
|
||||||
|
if (pth)
|
||||||
|
{
|
||||||
|
pthread_cancel(*pth);
|
||||||
|
pthread_join(*pth, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
@ -4959,6 +5045,16 @@ uint32_t gpioTick(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
unsigned gpioVersion(void)
|
||||||
|
{
|
||||||
|
DBG(DBG_USER, "");
|
||||||
|
|
||||||
|
return PIGPIO_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
unsigned gpioHardwareRevision(void)
|
unsigned gpioHardwareRevision(void)
|
||||||
|
|
95
pigpio.h
95
pigpio.h
|
@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This version is for pigpio version 9
|
This version is for pigpio version 10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PIGPIO_H
|
#ifndef PIGPIO_H
|
||||||
|
@ -51,6 +51,7 @@ This version is for pigpio version 9
|
||||||
/ output gpio level changes. /
|
/ output gpio level changes. /
|
||||||
/ 9) rudimentary permission control through the socket and pipe interfaces /
|
/ 9) rudimentary permission control through the socket and pipe interfaces /
|
||||||
/ so users can be prevented from "updating" inappropriate gpios. /
|
/ so users can be prevented from "updating" inappropriate gpios. /
|
||||||
|
/ 10) a simple interface to start and stop new threads. /
|
||||||
/ /
|
/ /
|
||||||
/ NOTE: /
|
/ NOTE: /
|
||||||
/ /
|
/ /
|
||||||
|
@ -83,8 +84,9 @@ This version is for pigpio version 9
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#define PIGPIO_VERSION 9
|
#define PIGPIO_VERSION 10
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -154,6 +156,9 @@ gpioSetGetSamplesFuncEx Requests a gpio samples callback, extended.
|
||||||
gpioSetTimerFunc Request a regular timed callback.
|
gpioSetTimerFunc Request a regular timed callback.
|
||||||
gpioSetTimerFuncEx Request a regular timed callback, extended.
|
gpioSetTimerFuncEx Request a regular timed callback, extended.
|
||||||
|
|
||||||
|
gpioStartThread Start a new thread.
|
||||||
|
gpioStopThread Stop a previously started thread.
|
||||||
|
|
||||||
gpioSetSignalFunc Request a signal callback.
|
gpioSetSignalFunc Request a signal callback.
|
||||||
gpioSetSignalFuncEx Request a signal callback, extended.
|
gpioSetSignalFuncEx Request a signal callback, extended.
|
||||||
|
|
||||||
|
@ -175,6 +180,8 @@ gpioTick Get current tick (microseconds).
|
||||||
|
|
||||||
gpioHardwareRevision Get hardware version.
|
gpioHardwareRevision Get hardware version.
|
||||||
|
|
||||||
|
gpioVersion Get the pigpio version.
|
||||||
|
|
||||||
gpioCfgBufferSize Configure the gpio sample buffer size.
|
gpioCfgBufferSize Configure the gpio sample buffer size.
|
||||||
gpioCfgClock Configure the gpio sample rate.
|
gpioCfgClock Configure the gpio sample rate.
|
||||||
gpioCfgDMAchannel Configure the DMA channel (DEPRECATED).
|
gpioCfgDMAchannel Configure the DMA channel (DEPRECATED).
|
||||||
|
@ -264,11 +271,15 @@ typedef void (*gpioGetSamplesFuncEx_t) (const gpioSample_t * samples,
|
||||||
int numSamples,
|
int numSamples,
|
||||||
void * userdata);
|
void * userdata);
|
||||||
|
|
||||||
|
typedef void *(ThreadFunc_t) (void *);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
All the functions which return an int return < 0 on error.
|
All the functions which return an int return < 0 on error.
|
||||||
|
|
||||||
If the library isn't initialised all but the gpioCfg* functions
|
If the library isn't initialised all but the gpioCfg*, gpioVersion,
|
||||||
will return error PI_NOT_INITIALISED.
|
and gpioHardwareRevision functions will return error PI_NOT_INITIALISED.
|
||||||
|
|
||||||
If the library is initialised the gpioCfg* functions will
|
If the library is initialised the gpioCfg* functions will
|
||||||
return error PI_INITIALISED.
|
return error PI_INITIALISED.
|
||||||
|
@ -1255,6 +1266,68 @@ int gpioSetTimerFuncEx(unsigned timer,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
pthread_t *gpioStartThread(ThreadFunc_t func, void *arg);
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
/* Starts a new thread of execution with func as the main routine.
|
||||||
|
|
||||||
|
Returns a pointer to pthread_t if OK, otherwise NULL.
|
||||||
|
|
||||||
|
The function is passed the single argument arg.
|
||||||
|
|
||||||
|
The thread can be cancelled by passing the pointer to pthread_t to
|
||||||
|
gpioStopThread().
|
||||||
|
|
||||||
|
EXAMPLE:
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <pigpio.h>
|
||||||
|
|
||||||
|
void *myfunc(void *arg)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
printf("%s\n", arg);
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
pthread_t *p1, *p2, *p3;
|
||||||
|
|
||||||
|
if (gpioInitialise() < 0) return 1;
|
||||||
|
|
||||||
|
p1 = gpioStartThread(myfunc, "thread 1"); sleep(3);
|
||||||
|
|
||||||
|
p2 = gpioStartThread(myfunc, "thread 2"); sleep(3);
|
||||||
|
|
||||||
|
p3 = gpioStartThread(myfunc, "thread 3"); sleep(3);
|
||||||
|
|
||||||
|
gpioStopThread(p3); sleep(3);
|
||||||
|
|
||||||
|
gpioStopThread(p2); sleep(3);
|
||||||
|
|
||||||
|
gpioStopThread(p1); sleep(3);
|
||||||
|
|
||||||
|
gpioTerminate();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
void gpioStopThread(pthread_t *pth);
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
/* Cancels the thread pointed at by pth.
|
||||||
|
|
||||||
|
No value is returned.
|
||||||
|
|
||||||
|
The thread to be stopped should have been started with gpioStartThread().
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
int gpioSetSignalFunc(unsigned signum,
|
int gpioSetSignalFunc(unsigned signum,
|
||||||
gpioSignalFunc_t f);
|
gpioSignalFunc_t f);
|
||||||
|
@ -1525,6 +1598,14 @@ unsigned gpioHardwareRevision(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
unsigned gpioVersion(void);
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
/* Returns the pigpio version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
int gpioCfgBufferSize(unsigned millis);
|
int gpioCfgBufferSize(unsigned millis);
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
@ -1734,6 +1815,7 @@ void gpioWaveDump(void);
|
||||||
#define PI_CMD_PFG 23
|
#define PI_CMD_PFG 23
|
||||||
#define PI_CMD_PRRG 24
|
#define PI_CMD_PRRG 24
|
||||||
#define PI_CMD_HELP 25
|
#define PI_CMD_HELP 25
|
||||||
|
#define PI_CMD_PIGPV 26
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following command only works on the socket interface.
|
The following command only works on the socket interface.
|
||||||
|
@ -1792,8 +1874,8 @@ after this command is issued.
|
||||||
#define PI_TOO_MANY_PULSES -36 /* waveform has too many pulses */
|
#define PI_TOO_MANY_PULSES -36 /* waveform has too many pulses */
|
||||||
#define PI_TOO_MANY_CHARS -37 /* waveform has too many chars */
|
#define PI_TOO_MANY_CHARS -37 /* waveform has too many chars */
|
||||||
#define PI_NOT_SERIAL_GPIO -38 /* no serial read in progress on gpio */
|
#define PI_NOT_SERIAL_GPIO -38 /* no serial read in progress on gpio */
|
||||||
#define PI_BAD_SERIAL_STRUC -39 /* bad null serial structure parameter */
|
#define PI_BAD_SERIAL_STRUC -39 /* bad (null) serial structure parameter */
|
||||||
#define PI_BAD_SERIAL_BUF -40 /* bad null serial buf parameter */
|
#define PI_BAD_SERIAL_BUF -40 /* bad (null) serial buf parameter */
|
||||||
#define PI_NOT_PERMITTED -41 /* gpio operation not permitted */
|
#define PI_NOT_PERMITTED -41 /* gpio operation not permitted */
|
||||||
#define PI_SOME_PERMITTED -42 /* one or more gpios not permitted */
|
#define PI_SOME_PERMITTED -42 /* one or more gpios not permitted */
|
||||||
|
|
||||||
|
@ -1816,3 +1898,4 @@ after this command is issued.
|
||||||
#define PI_DEFAULT_UPDATE_MASK_R2 0xFBC6CF9C
|
#define PI_DEFAULT_UPDATE_MASK_R2 0xFBC6CF9C
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
43
pigpio.py
43
pigpio.py
|
@ -76,7 +76,7 @@ import threading
|
||||||
import os
|
import os
|
||||||
import atexit
|
import atexit
|
||||||
|
|
||||||
VERSION = "1.0"
|
VERSION = "1.1"
|
||||||
|
|
||||||
# gpio levels
|
# gpio levels
|
||||||
|
|
||||||
|
@ -92,9 +92,9 @@ TIMEOUT = 2
|
||||||
|
|
||||||
# gpio edges
|
# gpio edges
|
||||||
|
|
||||||
EITHER_EDGE = 0
|
RISING_EDGE = 0
|
||||||
RISING_EDGE = 1
|
FALLING_EDGE = 1
|
||||||
FALLING_EDGE = 2
|
EITHER_EDGE = 2
|
||||||
|
|
||||||
# gpio modes
|
# gpio modes
|
||||||
|
|
||||||
|
@ -338,12 +338,14 @@ class _callback_thread(threading.Thread):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialises notifications."""
|
"""Initialises notifications."""
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
self.go = False
|
||||||
self.daemon = True
|
self.daemon = True
|
||||||
self.monitor = 0
|
self.monitor = 0
|
||||||
self.callbacks = []
|
self.callbacks = []
|
||||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.sock.connect((_host,_port))
|
self.sock.connect((_host,_port))
|
||||||
self.handle = _pigpio_command(self.sock, _PI_CMD_NOIB, 0, 0)
|
self.handle = _pigpio_command(self.sock, _PI_CMD_NOIB, 0, 0)
|
||||||
|
self.go = True
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
@ -376,13 +378,23 @@ class _callback_thread(threading.Thread):
|
||||||
notify_begin(self.handle, self.monitor)
|
notify_begin(self.handle, self.monitor)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
"""Execute the notification thread."""
|
"""Execute the notification thread."""
|
||||||
self.go = True
|
|
||||||
lastLevel = 0
|
lastLevel = 0
|
||||||
|
|
||||||
|
MSG_SIZ = 12
|
||||||
|
|
||||||
while self.go:
|
while self.go:
|
||||||
seq_no, flags, tick, level = (
|
|
||||||
struct.unpack('HHII', self.sock.recv(12, socket.MSG_WAITALL)))
|
buf = self.sock.recv(MSG_SIZ)
|
||||||
|
|
||||||
|
while self.go and len(buf) < MSG_SIZ:
|
||||||
|
buf += self.sock.recv(MSG_SIZ-len(buf))
|
||||||
|
|
||||||
if self.go:
|
if self.go:
|
||||||
|
seq, flags, tick, level = (struct.unpack('HHII', buf))
|
||||||
|
|
||||||
if flags == 0:
|
if flags == 0:
|
||||||
changed = level ^ lastLevel
|
changed = level ^ lastLevel
|
||||||
lastLevel = level
|
lastLevel = level
|
||||||
|
@ -391,9 +403,7 @@ class _callback_thread(threading.Thread):
|
||||||
newLevel = 0
|
newLevel = 0
|
||||||
if cb.bit & level:
|
if cb.bit & level:
|
||||||
newLevel = 1
|
newLevel = 1
|
||||||
if (cb.edge == EITHER_EDGE or
|
if (cb.edge ^ newLevel):
|
||||||
cb.edge == RISING_EDGE and newLevel == 1 or
|
|
||||||
cb.edge == FALLING_EDGE and newLevel == 0):
|
|
||||||
cb.func(cb.gpio, newLevel, tick)
|
cb.func(cb.gpio, newLevel, tick)
|
||||||
else:
|
else:
|
||||||
gpio = flags & 31
|
gpio = flags & 31
|
||||||
|
@ -404,6 +414,7 @@ class _callback_thread(threading.Thread):
|
||||||
self.sock.close()
|
self.sock.close()
|
||||||
|
|
||||||
class _wait_for_edge:
|
class _wait_for_edge:
|
||||||
|
|
||||||
"""A class to encapsulate waiting for gpio edges."""
|
"""A class to encapsulate waiting for gpio edges."""
|
||||||
|
|
||||||
def __init__(self, gpio, edge, timeout):
|
def __init__(self, gpio, edge, timeout):
|
||||||
|
@ -1553,20 +1564,18 @@ def start(host = os.getenv("PIGPIO_ADDR", ''),
|
||||||
else:
|
else:
|
||||||
h = _host
|
h = _host
|
||||||
errStr = "Can't connect to pigpio on " + str(h) + "(" + str(_port) + ")"
|
errStr = "Can't connect to pigpio on " + str(h) + "(" + str(_port) + ")"
|
||||||
print("********************************************************")
|
print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
|
||||||
print(errStr)
|
print(errStr)
|
||||||
print("")
|
print("")
|
||||||
print("Did you start the pigpio daemon?")
|
print("Did you start the pigpio daemon? E.g. sudo pigpiod")
|
||||||
print("(sudo pigpiod)")
|
|
||||||
print("")
|
print("")
|
||||||
print("Did you specify the correct Pi host/port in the environment")
|
print("Did you specify the correct Pi host/port in the environment")
|
||||||
print("variables PIGPIO_ADDR/PIGPIO_PORT?")
|
print("variables PIGPIO_ADDR/PIGPIO_PORT?")
|
||||||
print("(e.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888)")
|
print("E.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888")
|
||||||
print("")
|
print("")
|
||||||
print("Did you specify the correct Pi host/port in the")
|
print("Did you specify the correct Pi host/port in the")
|
||||||
print("pigpio.start() function")
|
print("pigpio.start() function? E.g. pigpio.start('soft', 8888))")
|
||||||
print("(e.g. pigpio.start('soft', 8888))")
|
print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
|
||||||
print("********************************************************")
|
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def stop():
|
def stop():
|
||||||
|
|
|
@ -0,0 +1,688 @@
|
||||||
|
/*
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* PIGPIOD_IF_VERSION 1 */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "pigpio.h"
|
||||||
|
#include "command.h"
|
||||||
|
|
||||||
|
#include "pigpiod_if.h"
|
||||||
|
|
||||||
|
#define PISCOPE_MAX_REPORTS_PER_READ 4096
|
||||||
|
|
||||||
|
#define STACK_SIZE (256*1024)
|
||||||
|
|
||||||
|
typedef void (*CBF_t) ();
|
||||||
|
|
||||||
|
struct callback_s
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
int gpio;
|
||||||
|
int edge;
|
||||||
|
CBF_t f;
|
||||||
|
void * user;
|
||||||
|
int ex;
|
||||||
|
callback_t *prev;
|
||||||
|
callback_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* GLOBALS ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static gpioReport_t gReport[PISCOPE_MAX_REPORTS_PER_READ];
|
||||||
|
|
||||||
|
static int gPigCommand = -1;
|
||||||
|
static int gPigHandle = -1;
|
||||||
|
static int gPigNotify = -1;
|
||||||
|
|
||||||
|
static uint32_t gNotifyBits;
|
||||||
|
|
||||||
|
callback_t *gCallBackFirst = 0;
|
||||||
|
callback_t *gCallBackLast = 0;
|
||||||
|
|
||||||
|
static int gPigStarted = 0;
|
||||||
|
|
||||||
|
static pthread_t *pthNotify;
|
||||||
|
|
||||||
|
/* PRIVATE ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static int pigpio_command(int fd, int command, int p1, int p2)
|
||||||
|
{
|
||||||
|
cmdCmd_t cmd;
|
||||||
|
|
||||||
|
cmd.cmd = command;
|
||||||
|
cmd.p1 = p1;
|
||||||
|
cmd.p2 = p2;
|
||||||
|
cmd.res = 0;
|
||||||
|
|
||||||
|
if (send(fd, &cmd, sizeof(cmdCmd_t), 0) != sizeof(cmdCmd_t))
|
||||||
|
return pigif_bad_send;
|
||||||
|
|
||||||
|
if (recv(fd, &cmd, sizeof(cmdCmd_t), MSG_WAITALL) != sizeof(cmdCmd_t))
|
||||||
|
return pigif_bad_recv;
|
||||||
|
|
||||||
|
return cmd.res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pigpioOpenSocket(char *addr, char *port)
|
||||||
|
{
|
||||||
|
int sock, err;
|
||||||
|
struct addrinfo hints, *res, *rp;
|
||||||
|
const char *addrStr, *portStr;
|
||||||
|
|
||||||
|
if (!addr)
|
||||||
|
{
|
||||||
|
addrStr = getenv(PI_ENVADDR);
|
||||||
|
|
||||||
|
if ((!addrStr) || (!strlen(addrStr)))
|
||||||
|
{
|
||||||
|
addrStr = PI_DEFAULT_SOCKET_ADDR_STR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else addrStr = addr;
|
||||||
|
|
||||||
|
if (!port)
|
||||||
|
{
|
||||||
|
portStr = getenv(PI_ENVPORT);
|
||||||
|
|
||||||
|
if ((!portStr) || (!strlen(portStr)))
|
||||||
|
{
|
||||||
|
portStr = PI_DEFAULT_SOCKET_PORT_STR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else portStr = port;
|
||||||
|
|
||||||
|
memset (&hints, 0, sizeof (hints));
|
||||||
|
|
||||||
|
hints.ai_family = PF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags |= AI_CANONNAME;
|
||||||
|
|
||||||
|
err = getaddrinfo (addrStr, portStr, &hints, &res);
|
||||||
|
|
||||||
|
if (err) return pigif_bad_getaddrinfo;
|
||||||
|
|
||||||
|
for (rp=res; rp!=NULL; rp=rp->ai_next)
|
||||||
|
{
|
||||||
|
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||||
|
|
||||||
|
if (sock == -1) continue;
|
||||||
|
|
||||||
|
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(res);
|
||||||
|
|
||||||
|
if (rp == NULL) return pigif_bad_connect;
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dispatch_notification(gpioReport_t *r)
|
||||||
|
{
|
||||||
|
static uint32_t lastLevel = 0;
|
||||||
|
|
||||||
|
callback_t *p;
|
||||||
|
uint32_t changed;
|
||||||
|
int l, g;
|
||||||
|
|
||||||
|
/*
|
||||||
|
printf("s=%d f=%d l=%8X, t=%10u\n",
|
||||||
|
r->seqno, r->flags, r->level, r->tick);
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (r->flags == 0)
|
||||||
|
{
|
||||||
|
changed = (r->level ^ lastLevel) & gNotifyBits;
|
||||||
|
|
||||||
|
lastLevel = r->level;
|
||||||
|
|
||||||
|
p = gCallBackFirst;
|
||||||
|
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
if (changed & (1<<(p->gpio)))
|
||||||
|
{
|
||||||
|
if ((r->level) & (1<<(p->gpio))) l = 1; else l = 0;
|
||||||
|
if ((p->edge) ^ l)
|
||||||
|
{
|
||||||
|
if (p->ex) (p->f)(p->gpio, l, r->tick, p->user);
|
||||||
|
else (p->f)(p->gpio, l, r->tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g = (r->flags) & 31;
|
||||||
|
|
||||||
|
p = gCallBackFirst;
|
||||||
|
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
if ((p->gpio) == g)
|
||||||
|
{
|
||||||
|
if (p->ex) (p->f)(g, PI_TIMEOUT, r->tick, p->user);
|
||||||
|
else (p->f)(g, PI_TIMEOUT, r->tick);
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *pthNotifyThread(void *x)
|
||||||
|
{
|
||||||
|
static int got = 0;
|
||||||
|
|
||||||
|
int bytes, r;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
bytes = read(gPigNotify, (char*)&gReport+got, sizeof(gReport)-got);
|
||||||
|
|
||||||
|
if (bytes > 0) got += bytes;
|
||||||
|
else break;
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
|
||||||
|
while (got >= sizeof(gpioReport_t))
|
||||||
|
{
|
||||||
|
dispatch_notification(&gReport[r]);
|
||||||
|
|
||||||
|
r++;
|
||||||
|
|
||||||
|
got -= sizeof(gpioReport_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy any partial report to start of array */
|
||||||
|
|
||||||
|
if (got && r) gReport[0] = gReport[r];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void findNotifyBits(void)
|
||||||
|
{
|
||||||
|
callback_t *p;
|
||||||
|
uint32_t bits = 0;
|
||||||
|
|
||||||
|
p = gCallBackFirst;
|
||||||
|
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
bits |= (1<<(p->gpio));
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits != gNotifyBits)
|
||||||
|
{
|
||||||
|
gNotifyBits = bits;
|
||||||
|
pigpio_command(gPigCommand, PI_CMD_NB, gPigHandle, gNotifyBits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _wfe(int gpio, int level, uint32_t tick, void *user)
|
||||||
|
{
|
||||||
|
*(int *)user = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int intCallback(int gpio, int edge, void *f, void *user, int ex)
|
||||||
|
{
|
||||||
|
static int id = 0;
|
||||||
|
callback_t *p;
|
||||||
|
|
||||||
|
if ((gpio >=0) && (gpio < 32) && (edge >=0) && (edge <= 2) && f)
|
||||||
|
{
|
||||||
|
/* prevent duplicates */
|
||||||
|
|
||||||
|
p = gCallBackFirst;
|
||||||
|
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
if ((p->gpio == gpio) && (p->edge == edge) && (p->f == f))
|
||||||
|
{
|
||||||
|
return pigif_duplicate_callback;
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = malloc(sizeof(callback_t));
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
if (!gCallBackFirst) gCallBackFirst = p;
|
||||||
|
|
||||||
|
p->id = id++;
|
||||||
|
p->gpio = gpio;
|
||||||
|
p->edge = edge;
|
||||||
|
p->f = f;
|
||||||
|
p->user = user;
|
||||||
|
p->ex = ex;
|
||||||
|
p->next = 0;
|
||||||
|
p->prev = gCallBackLast;
|
||||||
|
|
||||||
|
if (p->prev) (p->prev)->next = p;
|
||||||
|
gCallBackLast = p;
|
||||||
|
|
||||||
|
findNotifyBits();
|
||||||
|
|
||||||
|
return p->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pigif_bad_malloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pigif_bad_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PUBLIC ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double time_time(void)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
double t;
|
||||||
|
|
||||||
|
gettimeofday(&tv, 0);
|
||||||
|
|
||||||
|
t = (double)tv.tv_sec + ((double)tv.tv_usec / 1E6);
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void time_sleep(double seconds)
|
||||||
|
{
|
||||||
|
struct timespec ts, rem;
|
||||||
|
|
||||||
|
if (seconds > 0.0)
|
||||||
|
{
|
||||||
|
ts.tv_sec = seconds;
|
||||||
|
ts.tv_nsec = (seconds-(double)ts.tv_sec) * 1E9;
|
||||||
|
|
||||||
|
while (clock_nanosleep(CLOCK_REALTIME, 0, &ts, &rem))
|
||||||
|
{
|
||||||
|
/* copy remaining time to ts */
|
||||||
|
ts.tv_sec = rem.tv_sec;
|
||||||
|
ts.tv_nsec = rem.tv_nsec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *pigpio_error(int error)
|
||||||
|
{
|
||||||
|
if (error > -1000) return cmdErrStr(error);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(error)
|
||||||
|
{
|
||||||
|
case pigif_bad_send:
|
||||||
|
return "failed to send to pigpiod";
|
||||||
|
case pigif_bad_recv:
|
||||||
|
return "failed to receive from pigpiod";
|
||||||
|
case pigif_bad_getaddrinfo:
|
||||||
|
return "failed to find address of pigpiod";
|
||||||
|
case pigif_bad_connect:
|
||||||
|
return "failed to connect to pigpiod";
|
||||||
|
case pigif_bad_socket:
|
||||||
|
return "failed to create socket";
|
||||||
|
case pigif_bad_noib:
|
||||||
|
return "failed to open noib";
|
||||||
|
case pigif_duplicate_callback:
|
||||||
|
return "identical callback exists";
|
||||||
|
case pigif_bad_malloc:
|
||||||
|
return "failed to malloc";
|
||||||
|
case pigif_bad_callback:
|
||||||
|
return "bad callback parameter";
|
||||||
|
case pigif_notify_failed:
|
||||||
|
return "failed to create notification thread";
|
||||||
|
case pigif_callback_not_found:
|
||||||
|
return "callback not found";
|
||||||
|
default:
|
||||||
|
return "unknown error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned pigpiod_if_version(void)
|
||||||
|
{
|
||||||
|
return PIGPIOD_IF_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t *start_thread(ThreadFunc_t func, void *arg)
|
||||||
|
{
|
||||||
|
pthread_t *pth;
|
||||||
|
pthread_attr_t pthAttr;
|
||||||
|
|
||||||
|
pth = malloc(sizeof(pthread_t));
|
||||||
|
|
||||||
|
if (pth)
|
||||||
|
{
|
||||||
|
if (pthread_attr_init(&pthAttr))
|
||||||
|
{
|
||||||
|
perror("pthread_attr_init failed");
|
||||||
|
free(pth);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_attr_setstacksize(&pthAttr, STACK_SIZE))
|
||||||
|
{
|
||||||
|
perror("pthread_attr_setstacksize failed");
|
||||||
|
free(pth);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_create(pth, &pthAttr, func, arg))
|
||||||
|
{
|
||||||
|
perror("pthread_create socket failed");
|
||||||
|
free(pth);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop_thread(pthread_t *pth)
|
||||||
|
{
|
||||||
|
if (pth)
|
||||||
|
{
|
||||||
|
pthread_cancel(*pth);
|
||||||
|
pthread_join(*pth, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int pigpio_start(char *addrStr, char *portStr)
|
||||||
|
{
|
||||||
|
if (!gPigStarted)
|
||||||
|
{
|
||||||
|
gPigCommand = pigpioOpenSocket(addrStr, portStr);
|
||||||
|
|
||||||
|
if (gPigCommand >= 0)
|
||||||
|
{
|
||||||
|
gPigNotify = pigpioOpenSocket(addrStr, portStr);
|
||||||
|
|
||||||
|
if (gPigNotify >= 0)
|
||||||
|
{
|
||||||
|
gPigHandle = pigpio_command(gPigNotify, PI_CMD_NOIB, 0, 0);
|
||||||
|
|
||||||
|
if (gPigHandle < 0) return pigif_bad_noib;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pthNotify = start_thread(pthNotifyThread, 0);
|
||||||
|
if (pthNotify)
|
||||||
|
{
|
||||||
|
gPigStarted = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else return pigif_notify_failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else return gPigNotify;
|
||||||
|
}
|
||||||
|
else return gPigCommand;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pigpio_stop(void)
|
||||||
|
{
|
||||||
|
gPigStarted = 0;
|
||||||
|
|
||||||
|
if (pthNotify)
|
||||||
|
{
|
||||||
|
stop_thread(pthNotify);
|
||||||
|
pthNotify = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gPigNotify >= 0)
|
||||||
|
{
|
||||||
|
if (gPigHandle >= 0)
|
||||||
|
{
|
||||||
|
pigpio_command(gPigNotify, PI_CMD_NC, gPigHandle, 0);
|
||||||
|
gPigHandle = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(gPigNotify);
|
||||||
|
gPigNotify = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gPigCommand >= 0)
|
||||||
|
{
|
||||||
|
if (gPigHandle >= 0)
|
||||||
|
{
|
||||||
|
pigpio_command(gPigCommand, PI_CMD_NC, gPigHandle, 0);
|
||||||
|
gPigHandle = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(gPigCommand);
|
||||||
|
gPigCommand = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_mode(int gpio, int mode)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_MODES, gpio, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_mode(int gpio)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_MODEG, gpio, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_pull_up_down(int gpio, int pud)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_PUD, gpio, pud);
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_gpio(int gpio)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_READ, gpio, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_gpio(int gpio, int level)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_WRITE, gpio, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_PWM_dutycycle(int user_gpio, int dutycycle)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_PWM, user_gpio, dutycycle);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_PWM_range(int user_gpio, int range_)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_PRS, user_gpio, range_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_PWM_range(int user_gpio)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_PRG, user_gpio, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_PWM_real_range(int user_gpio)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_PRRG, user_gpio, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_PWM_frequency(int user_gpio, int frequency)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_PFS, user_gpio, frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_PWM_frequency(int user_gpio)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_PFG, user_gpio, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_servo_pulsewidth(int user_gpio, int pulsewidth)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_SERVO, user_gpio, pulsewidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
int notify_open(void)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_NO, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int notify_begin(int handle, uint32_t bits)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_NB, handle, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
int notify_pause(int handle)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_NB, handle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int notify_close(int handle)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_NC, handle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_watchdog(int user_gpio, int timeout)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_WDOG, user_gpio, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t read_bank_1(void)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_BR1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t read_bank_2(void)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_BR2, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int clear_bank_1(uint32_t levels)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_BC1, levels, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int clear_bank_2(uint32_t levels)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_BC2, levels, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_bank_1(uint32_t levels)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_BS1, levels, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_bank_2(uint32_t levels)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_BS2, levels, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_current_tick(void)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_TICK, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_hardware_revision(void)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_HWVER, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_pigpio_version(void)
|
||||||
|
{
|
||||||
|
return pigpio_command(gPigCommand, PI_CMD_PIGPV, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int callback(int gpio, int edge, CBFunc_t f)
|
||||||
|
{
|
||||||
|
return intCallback(gpio, edge, f, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user)
|
||||||
|
{
|
||||||
|
return intCallback(gpio, edge, f, user, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int callback_cancel(int id)
|
||||||
|
{
|
||||||
|
callback_t *p;
|
||||||
|
|
||||||
|
p = gCallBackFirst;
|
||||||
|
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
if (p->id == id)
|
||||||
|
{
|
||||||
|
if (p->prev) p->prev->next = p->next;
|
||||||
|
else gCallBackFirst = p->next;
|
||||||
|
|
||||||
|
if (p->next) p->next->prev = p->prev;
|
||||||
|
else gCallBackLast = p->prev;
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
findNotifyBits();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
return pigif_callback_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wait_for_edge(int gpio, int edge, double timeout)
|
||||||
|
{
|
||||||
|
int triggered = 0;
|
||||||
|
int id;
|
||||||
|
double due;
|
||||||
|
|
||||||
|
if (timeout <= 0.0) return 0;
|
||||||
|
|
||||||
|
due = time_time() + timeout;
|
||||||
|
|
||||||
|
id = callback_ex(gpio, edge, _wfe, &triggered);
|
||||||
|
|
||||||
|
while (!triggered && (time_time() < due)) time_sleep(0.1);
|
||||||
|
|
||||||
|
callback_cancel(id);
|
||||||
|
|
||||||
|
return triggered;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,527 @@
|
||||||
|
/*
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PIGPIOD_IF_H
|
||||||
|
#define PIGPIOD_IF_H
|
||||||
|
|
||||||
|
#include "pigpio.h"
|
||||||
|
|
||||||
|
#define PIGPIOD_IF_VERSION 1
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
pigif_bad_send = -2000,
|
||||||
|
pigif_bad_recv = -2001,
|
||||||
|
pigif_bad_getaddrinfo = -2002,
|
||||||
|
pigif_bad_connect = -2003,
|
||||||
|
pigif_bad_socket = -2004,
|
||||||
|
pigif_bad_noib = -2005,
|
||||||
|
pigif_duplicate_callback = -2006,
|
||||||
|
pigif_bad_malloc = -2007,
|
||||||
|
pigif_bad_callback = -2008,
|
||||||
|
pigif_notify_failed = -2009,
|
||||||
|
pigif_callback_not_found = -2010,
|
||||||
|
} piscopeError_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (*CBFunc_t) (int gpio, int level, uint32_t tick);
|
||||||
|
|
||||||
|
typedef void (*CBFuncEx_t)(int gpio, int level, uint32_t tick, void * user);
|
||||||
|
|
||||||
|
typedef struct callback_s callback_t;
|
||||||
|
|
||||||
|
#define RISING_EDGE 0
|
||||||
|
#define FALLING_EDGE 1
|
||||||
|
#define EITHER_EDGE 2
|
||||||
|
|
||||||
|
double time_time(void);
|
||||||
|
/* Return the current time in seconds since the Epoch.*/
|
||||||
|
|
||||||
|
void time_sleep(double seconds);
|
||||||
|
/* Delay execution for a given number of seconds */
|
||||||
|
|
||||||
|
const char *pigpio_error(int error);
|
||||||
|
/* Return a string for a pigpio library error. */
|
||||||
|
|
||||||
|
unsigned pigpiod_if_version(void);
|
||||||
|
/* Return the pigpiod_if version. */
|
||||||
|
|
||||||
|
pthread_t *start_thread(ThreadFunc_t func, void *arg);
|
||||||
|
/* Starts a new thread of execution with func as the main routine.
|
||||||
|
|
||||||
|
Returns a pointer to pthread_t if OK, otherwise NULL.
|
||||||
|
|
||||||
|
The function is passed the single argument arg.
|
||||||
|
|
||||||
|
The thread can be cancelled by passing the pointer to pthread_t to
|
||||||
|
gpioStopThread().
|
||||||
|
*/
|
||||||
|
|
||||||
|
void stop_thread(pthread_t *pth);
|
||||||
|
/* Cancels the thread pointed at by pth.
|
||||||
|
|
||||||
|
No value is returned.
|
||||||
|
|
||||||
|
The thread to be stopped should have been started with gpioStartThread().
|
||||||
|
*/
|
||||||
|
|
||||||
|
int pigpio_start(char *addrStr, char *portStr);
|
||||||
|
/* Connect to the pigpio daemon. Reserving command and
|
||||||
|
notification streams.
|
||||||
|
|
||||||
|
addrStr specifies the host or IP address of the Pi running
|
||||||
|
the pigpio daemon. It may be NULL in which case localhost
|
||||||
|
is used unless overriden by the PIGPIO_ADDR environment
|
||||||
|
variable.
|
||||||
|
|
||||||
|
portStr specifies the port address used by the Pi running
|
||||||
|
the pigpio daemon. It may be NULL in which case "8888"
|
||||||
|
is used unless overriden by the PIGPIO_PORT environment
|
||||||
|
variable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void pigpio_stop(void);
|
||||||
|
/*
|
||||||
|
Terminates the connection to the pigpio daemon and releases
|
||||||
|
resources used by the library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int set_mode(int gpio, int mode);
|
||||||
|
/* Set the gpio mode.
|
||||||
|
|
||||||
|
gpio: 0-53.
|
||||||
|
mode: INPUT, OUTPUT, ALT0, ALT1, ALT2, ALT3, ALT4, ALT5.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_MODE,
|
||||||
|
or PI_NOT_PERMITTED.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int get_mode(int gpio);
|
||||||
|
/* Get the gpio mode.
|
||||||
|
|
||||||
|
Returns the gpio mode if OK, otherwise PI_BAD_GPIO.
|
||||||
|
|
||||||
|
gpio: 0-53.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int set_pull_up_down(int gpio, int pud);
|
||||||
|
/* Set or clear the gpio pull-up/down resistor.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_PUD,
|
||||||
|
or PI_NOT_PERMITTED.
|
||||||
|
|
||||||
|
gpio: 0-53.
|
||||||
|
pud: PUD_UP, PUD_DOWN, PUD_OFF.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int read_gpio(int gpio);
|
||||||
|
/* Read the gpio level.
|
||||||
|
|
||||||
|
Returns the gpio level if OK, otherwise PI_BAD_GPIO.
|
||||||
|
|
||||||
|
gpio:0-53.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int write_gpio(int gpio, int level);
|
||||||
|
/*
|
||||||
|
Write the gpio level.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_LEVEL,
|
||||||
|
or PI_NOT_PERMITTED.
|
||||||
|
|
||||||
|
gpio: 0-53.
|
||||||
|
level: 0, 1.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
|
||||||
|
If PWM or servo pulses are active on the gpio they are switched off.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int set_PWM_dutycycle(int user_gpio, int dutycycle);
|
||||||
|
/* Start (non-zero dutycycle) or stop (0) PWM pulses on the gpio.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_DUTYCYCLE,
|
||||||
|
or PI_NOT_PERMITTED.
|
||||||
|
|
||||||
|
user_gpio: 0-31.
|
||||||
|
dutycycle: 0-range (range defaults to 255).
|
||||||
|
|
||||||
|
Notes
|
||||||
|
|
||||||
|
The set_PWM_range() function can change the default range of 255.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int set_PWM_range(int user_gpio, int range_);
|
||||||
|
/* Set the range of PWM values to be used on the gpio.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_DUTYRANGE,
|
||||||
|
or PI_NOT_PERMITTED.
|
||||||
|
|
||||||
|
user_gpio: 0-31.
|
||||||
|
range_: 25-40000.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
|
||||||
|
If PWM is currently active on the gpio its dutycycle will be
|
||||||
|
scaled to reflect the new range.
|
||||||
|
|
||||||
|
The real range, the number of steps between fully off and fully on
|
||||||
|
for each of the 18 available gpio frequencies is
|
||||||
|
|
||||||
|
25(#1), 50(#2), 100(#3), 125(#4), 200(#5), 250(#6), 400(#7),
|
||||||
|
500(#8), 625(#9), 800(#10), 1000(#11), 1250(#12), 2000(#13),
|
||||||
|
2500(#14), 4000(#15), 5000(#16), 10000(#17), 20000(#18)
|
||||||
|
|
||||||
|
The real value set by set_PWM_range is
|
||||||
|
(dutycycle * real range) / range.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int get_PWM_range(int user_gpio);
|
||||||
|
/* Get the range of PWM values being used on the gpio.
|
||||||
|
|
||||||
|
Returns the dutycycle range used for the gpio if OK,
|
||||||
|
otherwise PI_BAD_USER_GPIO.
|
||||||
|
|
||||||
|
user_gpio: 0-31.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int get_PWM_real_range(int user_gpio);
|
||||||
|
/* Get the real underlying range of PWM values being used on the gpio.
|
||||||
|
|
||||||
|
Returns the real range used for the gpio if OK,
|
||||||
|
otherwise PI_BAD_USER_GPIO.
|
||||||
|
|
||||||
|
user_gpio: 0-31.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int set_PWM_frequency(int user_gpio, int frequency);
|
||||||
|
/*
|
||||||
|
Set the frequency (in Hz) of the PWM to be used on the gpio.
|
||||||
|
|
||||||
|
Returns the numerically closest frequency if OK, otherwise
|
||||||
|
PI_BAD_USER_GPIO or PI_NOT_PERMITTED.
|
||||||
|
|
||||||
|
user_gpio: 0-31.
|
||||||
|
frequency: 0- (Hz).
|
||||||
|
|
||||||
|
The selectable frequencies depend upon the sample rate which
|
||||||
|
may be 1, 2, 4, 5, 8, or 10 microseconds (default 5). The
|
||||||
|
sample rate is set when the C pigpio library is started.
|
||||||
|
|
||||||
|
Each gpio can be independently set to one of 18 different
|
||||||
|
PWM frequencies.
|
||||||
|
|
||||||
|
If PWM is currently active on the gpio it will be switched
|
||||||
|
off and then back on at the new frequency.
|
||||||
|
|
||||||
|
1us 40000, 20000, 10000, 8000, 5000, 4000, 2500, 2000, 1600,
|
||||||
|
1250, 1000, 800, 500, 400, 250, 200, 100, 50
|
||||||
|
|
||||||
|
2us 20000, 10000, 5000, 4000, 2500, 2000, 1250, 1000, 800,
|
||||||
|
625, 500, 400, 250, 200, 125, 100, 50, 25
|
||||||
|
|
||||||
|
4us 10000, 5000, 2500, 2000, 1250, 1000, 625, 500, 400,
|
||||||
|
313, 250, 200, 125, 100, 63, 50, 25, 13
|
||||||
|
|
||||||
|
5us 8000, 4000, 2000, 1600, 1000, 800, 500, 400, 320,
|
||||||
|
250, 200, 160, 100, 80, 50, 40, 20, 10
|
||||||
|
|
||||||
|
8us 5000, 2500, 1250, 1000, 625, 500, 313, 250, 200,
|
||||||
|
156, 125, 100, 63, 50, 31, 25, 13, 6
|
||||||
|
|
||||||
|
10us 4000, 2000, 1000, 800, 500, 400, 250, 200, 160,
|
||||||
|
125, 100, 80, 50, 40, 25, 20, 10, 5
|
||||||
|
*/
|
||||||
|
|
||||||
|
int get_PWM_frequency(int user_gpio);
|
||||||
|
/*
|
||||||
|
Get the frequency of PWM being used on the gpio.
|
||||||
|
|
||||||
|
Returns the frequency (in hertz) used for the gpio if OK,
|
||||||
|
otherwise PI_BAD_USER_GPIO.
|
||||||
|
|
||||||
|
user_gpio: 0-31.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int set_servo_pulsewidth(int user_gpio, int pulsewidth);
|
||||||
|
/*
|
||||||
|
Start (500-2500) or stop (0) servo pulses on the gpio.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_PULSEWIDTH or
|
||||||
|
PI_NOT_PERMITTED.
|
||||||
|
|
||||||
|
user_gpio: 0-31.
|
||||||
|
pulsewidth: 0 (off), 500 (most anti-clockwise) - 2500 (most clockwise).
|
||||||
|
|
||||||
|
The selected pulsewidth will continue to be transmitted until
|
||||||
|
changed by a subsequent call to set_servo_pulsewidth().
|
||||||
|
|
||||||
|
The pulsewidths supported by servos varies and should probably be
|
||||||
|
determined by experiment. A value of 1500 should always be safe and
|
||||||
|
represents the mid-point of rotation.
|
||||||
|
|
||||||
|
You can DAMAGE a servo if you command it to move beyond its limits.
|
||||||
|
|
||||||
|
OTHER UPDATE RATES:
|
||||||
|
|
||||||
|
This function updates servos at 50Hz. If you wish to use a different
|
||||||
|
update frequency you will have to use the PWM functions.
|
||||||
|
|
||||||
|
Update Rate (Hz) 50 100 200 400 500
|
||||||
|
1E6/Hz 20000 10000 5000 2500 2000
|
||||||
|
|
||||||
|
Firstly set the desired PWM frequency using set_PWM_frequency().
|
||||||
|
|
||||||
|
Then set the PWM range using set_PWM_range() to 1E6/Hz.
|
||||||
|
Doing this allows you to use units of microseconds when setting
|
||||||
|
the servo pulse width.
|
||||||
|
|
||||||
|
E.g. If you want to update a servo connected to gpio 25 at 400Hz
|
||||||
|
|
||||||
|
set_PWM_frequency(25, 400);
|
||||||
|
set_PWM_range(25, 2500);
|
||||||
|
|
||||||
|
Thereafter use the set_PWM_dutycycle() function to move the servo,
|
||||||
|
e.g. set_PWM_dutycycle(25, 1500) will set a 1500 us pulse.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int notify_open(void);
|
||||||
|
/*
|
||||||
|
Get a free notification handle.
|
||||||
|
|
||||||
|
Returns a handle greater than or equal to zero if OK,
|
||||||
|
otherwise PI_NO_HANDLE.
|
||||||
|
|
||||||
|
A notification is a method for being notified of gpio state
|
||||||
|
changes via a pipe.
|
||||||
|
|
||||||
|
Pipes are only accessible from the local machine so this function
|
||||||
|
serves no purpose if you are using the library from a remote machine.
|
||||||
|
The in-built (socket) notifications provided by callback()
|
||||||
|
should be used instead.
|
||||||
|
|
||||||
|
Notifications for handle x will be available at the pipe
|
||||||
|
named /dev/pigpiox (where x is the handle number).
|
||||||
|
E.g. if the function returns 15 then the notifications must be
|
||||||
|
read from /dev/pigpio15.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int notify_begin(int handle, uint32_t bits);
|
||||||
|
/*
|
||||||
|
Start notifications on a previously opened handle.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_BAD_HANDLE.
|
||||||
|
|
||||||
|
handle: 0-31 (as returned by notify_open())
|
||||||
|
bits: a mask indicating the gpios to be notified.
|
||||||
|
|
||||||
|
The notification sends state changes for each gpio whose
|
||||||
|
corresponding bit in bits is set.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
|
||||||
|
Each notification occupies 12 bytes in the fifo as follows:
|
||||||
|
|
||||||
|
H (16 bit) seqno
|
||||||
|
H (16 bit) flags
|
||||||
|
I (32 bit) tick
|
||||||
|
I (32 bit) level
|
||||||
|
*/
|
||||||
|
|
||||||
|
int notify_pause(int handle);
|
||||||
|
/*
|
||||||
|
Pause notifications on a previously opened handle.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_BAD_HANDLE.
|
||||||
|
|
||||||
|
handle: 0-31 (as returned by notify_open())
|
||||||
|
|
||||||
|
Notifications for the handle are suspended until
|
||||||
|
notify_begin() is called again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int notify_close(int handle);
|
||||||
|
/*
|
||||||
|
Stop notifications on a previously opened handle and
|
||||||
|
release the handle for reuse.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_BAD_HANDLE.
|
||||||
|
|
||||||
|
handle: 0-31 (as returned by notify_open())
|
||||||
|
*/
|
||||||
|
|
||||||
|
int set_watchdog(int user_gpio, int timeout);
|
||||||
|
/*
|
||||||
|
Sets a watchdog for a gpio.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_BAD_USER_GPIO
|
||||||
|
or PI_BAD_WDOG_TIMEOUT.
|
||||||
|
|
||||||
|
user_gpio: 0-31.
|
||||||
|
timeout: 0-60000.
|
||||||
|
|
||||||
|
The watchdog is nominally in milliseconds.
|
||||||
|
|
||||||
|
Only one watchdog may be registered per gpio.
|
||||||
|
|
||||||
|
The watchdog may be cancelled by setting timeout to 0.
|
||||||
|
|
||||||
|
If no level change has been detected for the gpio for timeout
|
||||||
|
milliseconds any notification for the gpio has a report written
|
||||||
|
to the fifo with the flags set to indicate a watchdog timeout.
|
||||||
|
|
||||||
|
The callback() and callback_ex functions interpret the flags and will
|
||||||
|
call registered callbacks for the gpio with level TIMEOUT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t read_bank_1(void);
|
||||||
|
/*
|
||||||
|
Read the levels of the bank 1 gpios (gpios 0-31).
|
||||||
|
|
||||||
|
The returned 32 bit integer has a bit set if the corresponding
|
||||||
|
gpio is logic 1. Gpio n has bit value (1<<n).
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t read_bank_2(void);
|
||||||
|
/*
|
||||||
|
Read the levels of the bank 2 gpios (gpios 32-53).
|
||||||
|
|
||||||
|
The returned 32 bit integer has a bit set if the corresponding
|
||||||
|
gpio is logic 1. Gpio n has bit value (1<<(n-32)).
|
||||||
|
*/
|
||||||
|
|
||||||
|
int clear_bank_1(uint32_t levels);
|
||||||
|
/*
|
||||||
|
Clears gpios 0-31 if the corresponding bit in levels is set.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_SOME_PERMITTED.
|
||||||
|
|
||||||
|
A status of PI_SOME_PERMITTED indicates that the user is not
|
||||||
|
allowed to write to one or more of the gpios.
|
||||||
|
|
||||||
|
levels: a bit mask with 1 set if the corresponding gpio is
|
||||||
|
to be cleared.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int clear_bank_2(uint32_t levels);
|
||||||
|
/*
|
||||||
|
Clears gpios 32-53 if the corresponding bit (0-21) in levels is set.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_SOME_PERMITTED.
|
||||||
|
|
||||||
|
A status of PI_SOME_PERMITTED indicates that the user is not
|
||||||
|
allowed to write to one or more of the gpios.
|
||||||
|
|
||||||
|
levels: a bit mask with 1 set if the corresponding gpio is
|
||||||
|
to be cleared.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int set_bank_1(uint32_t levels);
|
||||||
|
/*
|
||||||
|
Sets gpios 0-31 if the corresponding bit in levels is set.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_SOME_PERMITTED.
|
||||||
|
|
||||||
|
A status of PI_SOME_PERMITTED indicates that the user is not
|
||||||
|
allowed to write to one or more of the gpios.
|
||||||
|
|
||||||
|
levels: a bit mask with 1 set if the corresponding gpio is
|
||||||
|
to be set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int set_bank_2(uint32_t levels);
|
||||||
|
/*
|
||||||
|
Sets gpios 32-53 if the corresponding bit (0-21) in levels is set.
|
||||||
|
|
||||||
|
Returns 0 if OK, otherwise PI_SOME_PERMITTED.
|
||||||
|
|
||||||
|
A status of PI_SOME_PERMITTED indicates that the user is not
|
||||||
|
allowed to write to one or more of the gpios.
|
||||||
|
|
||||||
|
levels: a bit mask with 1 set if the corresponding gpio is
|
||||||
|
to be set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t get_current_tick(void);
|
||||||
|
/*
|
||||||
|
|
||||||
|
Gets the current system tick.
|
||||||
|
|
||||||
|
Tick is the number of microseconds since system boot.
|
||||||
|
|
||||||
|
As tick is an unsigned 32 bit quantity it wraps around after
|
||||||
|
2**32 microseconds, which is approximately 1 hour 12 minutes.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t get_hardware_revision(void);
|
||||||
|
/*
|
||||||
|
Get the Pi's hardware revision number.
|
||||||
|
|
||||||
|
It is unfortunate that Pi boards have been named Revision.1 and
|
||||||
|
Revision.2. That use of the word revision is distinct from the
|
||||||
|
Pi's hardware revision number.'
|
||||||
|
|
||||||
|
The hardware revision is the last 4 characters on the Revision line
|
||||||
|
of /proc/cpuinfo.
|
||||||
|
|
||||||
|
The revision number can be used to determine the assignment of gpios
|
||||||
|
to pins.
|
||||||
|
|
||||||
|
There are at least two types of board.
|
||||||
|
|
||||||
|
Type 1 has gpio 0 on P1-3, gpio 1 on P1-5, and gpio 21 on P1-13.
|
||||||
|
Type 2 has gpio 2 on P1-3, gpio 3 on P1-5, gpio 27 on P1-13, and
|
||||||
|
gpios 28-31 on P5.
|
||||||
|
|
||||||
|
Type 1 boards have hardware revision numbers of 2 and 3.
|
||||||
|
|
||||||
|
Type 2 boards have hardware revision numbers of 4, 5, 6, and 15.
|
||||||
|
|
||||||
|
If the hardware revision can not be found or is not a valid
|
||||||
|
hexadecimal number the function returns 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int callback(int gpio, int edge, CBFunc_t f);
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user);
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int callback_cancel(int id);
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int wait_for_edge(int gpio, int edge, double timeout);
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -3,7 +3,7 @@
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
|
|
||||||
setup(name='pigpio',
|
setup(name='pigpio',
|
||||||
version='1.0',
|
version='1.1',
|
||||||
author='joan',
|
author='joan',
|
||||||
author_email='joan@abyz.me.uk',
|
author_email='joan@abyz.me.uk',
|
||||||
maintainer='joan',
|
maintainer='joan',
|
||||||
|
|
Loading…
Reference in New Issue