diff --git a/MakeRemote b/MakeRemote index 14dd622..586cbf8 100644 --- a/MakeRemote +++ b/MakeRemote @@ -4,43 +4,56 @@ SIZE = size SHLIB = gcc -shared STRIPLIB = strip --strip-unneeded -CFLAGS += -O3 -Wall +CFLAGS += -O3 -Wall -pthread -ALL = libpigpiod_if.so pigs +ALL = libpigpiod_if.so libpigpiod_if2.so pigs x_pigpiod_if x_pigpiod_if2 all: $(ALL) pigpio.py setup.py pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h $(CC) $(CFLAGS) -fpic -c -o pigpiod_if.o pigpiod_if.c +pigpiod_if2.o: pigpiod_if2.c pigpio.h command.h pigpiod_if2.h + $(CC) $(CFLAGS) -fpic -c -o pigpiod_if2.o pigpiod_if2.c + command.o: command.c pigpio.h command.h $(CC) $(CFLAGS) -fpic -c -o command.o command.c - pigs: command.o pigs.o $(CC) $(CFLAGS) -fpic -o pigs pigs.c command.c +x_pigpiod_if: x_pigpiod_if.o $(LIB1) + $(CC) -o x_pigpiod_if x_pigpiod_if.o $(LL1) + +x_pigpiod_if2: x_pigpiod_if2.o $(LIB2) + $(CC) -o x_pigpiod_if2 x_pigpiod_if2.o $(LL2) + clean: rm -f *.o *.i *.s *~ $(ALL) -install: $(LIB) - install -m 0755 -d /usr/local/include - install -m 0644 pigpio.h /usr/local/include - install -m 0644 pigpiod_if.h /usr/local/include - install -m 0755 -d /usr/local/lib - install -m 0644 libpigpiod_if.so /usr/local/lib - install -m 0755 -d /usr/local/bin - install -m 0755 pigs /usr/local/bin +install: $(LIB1) $(LIB2) + install -m 0755 -d /usr/local/include + install -m 0644 pigpio.h /usr/local/include + install -m 0644 pigpiod_if.h /usr/local/include + install -m 0644 pigpiod_if2.h /usr/local/include + install -m 0755 -d /usr/local/lib + install -m 0644 libpigpiod_if.so /usr/local/lib + install -m 0644 libpigpiod_if2.so /usr/local/lib + install -m 0755 -d /usr/local/bin + install -m 0755 pigs /usr/local/bin python2 setup.py install python3 setup.py install - install -m 0755 -d /usr/local/man/man1 - install -m 0644 *.1 /usr/local/man/man1 - install -m 0755 -d /usr/local/man/man3 - install -m 0644 *.3 /usr/local/man/man3 + install -m 0755 -d /usr/local/man/man1 + install -m 0644 *.1 /usr/local/man/man1 + install -m 0755 -d /usr/local/man/man3 + install -m 0644 *.3 /usr/local/man/man3 uninstall: rm -f /usr/local/include/pigpio.h + rm -f /usr/local/include/pigpiod_if.h + rm -f /usr/local/include/pigpiod_if2.h rm -f /usr/local/lib/libpigpiod_if.so + rm -f /usr/local/lib/libpigpiod_if2.so echo removing python2 files python2 setup.py install --record /tmp/pigpio >/dev/null xargs rm -f < /tmp/pigpio >/dev/null @@ -51,18 +64,30 @@ uninstall: rm -f /usr/local/man/man1/pig*.1 rm -f /usr/local/man/man3/pig*.3 -LIB = libpigpiod_if.so -OBJ = pigpiod_if.o command.o +LL1 = -L. -lpigpiod_if -pthread -lrt +LL2 = -L. -lpigpiod_if2 -pthread -lrt -$(LIB): $(OBJ) - $(SHLIB) -o $(LIB) $(OBJ) - $(STRIPLIB) $(LIB) - $(SIZE) $(LIB) +LIB1 = libpigpiod_if.so +OBJ1 = pigpiod_if.o command.o + +LIB2 = libpigpiod_if2.so +OBJ2 = pigpiod_if2.o command.o + +$(LIB1): $(OBJ1) + $(SHLIB) -o $(LIB1) $(OBJ1) + $(STRIPLIB) $(LIB1) + $(SIZE) $(LIB1) + +$(LIB2): $(OBJ2) + $(SHLIB) -o $(LIB2) $(OBJ2) + $(STRIPLIB) $(LIB2) + $(SIZE) $(LIB2) # generated using gcc -MM *.c command.o: command.c pigpio.h command.h pigpiod.o: pigpiod.c pigpio.h pigpiod_if.o: pigpiod_if.c pigpio.h pigpiod_if.h command.h +pigpiod_if2.o: pigpiod_if2.c pigpio.h pigpiod_if2.h command.h pigs.o: pigs.c pigpio.h command.h diff --git a/Makefile b/Makefile index bf8155e..5a0ba83 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ SIZE = size SHLIB = gcc -shared STRIPLIB = strip --strip-unneeded -CFLAGS += -O3 -Wall +CFLAGS += -O3 -Wall -pthread LIB1 = libpigpio.so OBJ1 = pigpio.o command.o @@ -14,13 +14,18 @@ OBJ1 = pigpio.o command.o LIB2 = libpigpiod_if.so OBJ2 = pigpiod_if.o command.o -LIB = $(LIB1) $(LIB2) +LIB3 = libpigpiod_if2.so +OBJ3 = pigpiod_if2.o command.o -ALL = $(LIB) x_pigpio x_pigpiod_if pig2vcd pigpiod pigs +LIB = $(LIB1) $(LIB2) $(LIB3) -LL1 = -L. -lpigpio -lpthread -lrt +ALL = $(LIB) x_pigpio x_pigpiod_if x_pigpiod_if2 pig2vcd pigpiod pigs -LL2 = -L. -lpigpiod_if -lpthread -lrt +LL1 = -L. -lpigpio -pthread -lrt + +LL2 = -L. -lpigpiod_if -pthread -lrt + +LL3 = -L. -lpigpiod_if2 -pthread -lrt all: $(ALL) @@ -30,6 +35,9 @@ pigpio.o: pigpio.c pigpio.h command.h custom.cext pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h $(CC) $(CFLAGS) -fpic -c -o pigpiod_if.o pigpiod_if.c +pigpiod_if2.o: pigpiod_if2.c pigpio.h command.h pigpiod_if2.h + $(CC) $(CFLAGS) -fpic -c -o pigpiod_if2.o pigpiod_if2.c + command.o: command.c pigpio.h command.h $(CC) $(CFLAGS) -fpic -c -o command.o command.c @@ -39,6 +47,9 @@ x_pigpio: x_pigpio.o $(LIB1) x_pigpiod_if: x_pigpiod_if.o $(LIB2) $(CC) -o x_pigpiod_if x_pigpiod_if.o $(LL2) +x_pigpiod_if2: x_pigpiod_if2.o $(LIB3) + $(CC) -o x_pigpiod_if2 x_pigpiod_if2.o $(LL3) + pigpiod: pigpiod.o $(LIB1) $(CC) -o pigpiod pigpiod.o $(LL1) @@ -52,30 +63,34 @@ clean: rm -f *.o *.i *.s *~ $(ALL) install: $(ALL) - install -m 0755 -d /opt/pigpio/cgi - install -m 0755 -d /usr/local/include - install -m 0644 pigpio.h /usr/local/include - install -m 0644 pigpiod_if.h /usr/local/include - install -m 0755 -d /usr/local/lib - install -m 0755 libpigpio.so /usr/local/lib - install -m 0755 libpigpiod_if.so /usr/local/lib - install -m 0755 -d /usr/local/bin - install -m 0755 -s pig2vcd /usr/local/bin - install -m 0755 -s pigpiod /usr/local/bin - install -m 0755 -s pigs /usr/local/bin + install -m 0755 -d /opt/pigpio/cgi + install -m 0755 -d /usr/local/include + install -m 0644 pigpio.h /usr/local/include + install -m 0644 pigpiod_if.h /usr/local/include + install -m 0644 pigpiod_if2.h /usr/local/include + install -m 0755 -d /usr/local/lib + install -m 0755 libpigpio.so /usr/local/lib + install -m 0755 libpigpiod_if.so /usr/local/lib + install -m 0755 libpigpiod_if2.so /usr/local/lib + install -m 0755 -d /usr/local/bin + install -m 0755 -s pig2vcd /usr/local/bin + install -m 0755 -s pigpiod /usr/local/bin + install -m 0755 -s pigs /usr/local/bin if which python2; then python2 setup.py install; fi if which python3; then python3 setup.py install; fi - install -m 0755 -d /usr/local/man/man1 - install -m 0644 *.1 /usr/local/man/man1 - install -m 0755 -d /usr/local/man/man3 - install -m 0644 *.3 /usr/local/man/man3 + install -m 0755 -d /usr/local/man/man1 + install -m 0644 *.1 /usr/local/man/man1 + install -m 0755 -d /usr/local/man/man3 + install -m 0644 *.3 /usr/local/man/man3 ldconfig uninstall: rm -f /usr/local/include/pigpio.h rm -f /usr/local/include/pigpiod_if.h + rm -f /usr/local/include/pigpiod_if2.h rm -f /usr/local/lib/libpigpio.so rm -f /usr/local/lib/libpigpiod_if.so + rm -f /usr/local/lib/libpigpiod_if2.so rm -f /usr/local/bin/pig2vcd rm -f /usr/local/bin/pigpiod rm -f /usr/local/bin/pigs @@ -95,6 +110,11 @@ $(LIB2): $(OBJ2) $(STRIPLIB) $(LIB2) $(SIZE) $(LIB2) +$(LIB3): $(OBJ3) + $(SHLIB) -o $(LIB3) $(OBJ3) + $(STRIPLIB) $(LIB3) + $(SIZE) $(LIB3) + # generated using gcc -MM *.c pig2vcd.o: pig2vcd.c pigpio.h @@ -102,3 +122,4 @@ pigpiod.o: pigpiod.c pigpio.h pigs.o: pigs.c pigpio.h command.h x_pigpio.o: x_pigpio.c pigpio.h x_pigpiod_if.o: x_pigpiod_if.c pigpiod_if.h pigpio.h +x_pigpiod_if2.o: x_pigpiod_if2.c pigpiod_if2.h pigpio.h diff --git a/README b/README index bb18a21..3f3d766 100644 --- a/README +++ b/README @@ -13,18 +13,20 @@ IN THAT DIRECTORY Enter the following two commands (in this order) make -make install +sudo make install This will install o the library (libpigpio.so) in /usr/local/lib o the library (libpigpiod_if.so) in /usr/local/lib +o the library (libpigpiod_if2.so) 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 header file (pigpiod_if2.h) in /usr/local/include 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 man pages in /usr/local/man/man1 and man3 +o man pages in /usr/local/man/man1 and /usr/local/man/man3 o the Python module pigpio.py for Python 2 and 3 TEST (optional) @@ -48,19 +50,21 @@ To test the pigpio daemon do sudo pigpiod -./x_pigpiod_if # test the C I/F to the pigpio daemon -./x_pigpio.py # test the Python I/F to the pigpio daemon -./x_pigs # test the socket I/F to the pigpio daemon -./x_pipe # test the pipe I/F to the pigpio daemon +./x_pigpiod_if # test the C I/F to the pigpio daemon +./x_pigpiod_if2 # test the C I/F to the pigpio daemon +./x_pigpio.py # test the Python I/F to the pigpio daemon +./x_pigs # test the socket I/F to the pigpio daemon +./x_pipe # test the pipe I/F to the pigpio daemon EXAMPLE CODE x_pigpio.c, pig2vcd.c, and pigpiod.c show examples of interfacing with the pigpio library. -pigs.c, pigpio.py, x_pigpiod_if.c, x_pigpio.py, x_pigs, and x_pipe -show examples of interfacing with the pigpio daemon. x_pipe uses -the pipe interface, the others use the socket interface. +pigs.c, pigpio.py, x_pigpiod_if, x_pigpiod_if2.c, x_pigpio.py, +x_pigs, and x_pipe show examples of interfacing with the pigpio +daemon. x_pipe uses the pipe interface, the others use the +socket interface. DAEMON @@ -123,6 +127,7 @@ 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) +o the C socket I/F using libpigpiod_if2 (header file pigpiod_if2.h) On a Linux machine @@ -133,10 +138,12 @@ make -f MakeRemote install This will install o the library (libpigpiod_if.so) in /usr/local/lib +o the library (libpigpiod_if2.so) 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 header file (pigpiod_if2.h) in /usr/local/include o the socket interface (pigs) in /usr/local/bin -o man pages in /usr/local/man/man1 and man3 +o man pages in /usr/local/man/man1 and /usr/local/man/man3 o the Python module pigpio.py On Windows machines (and possibly Macs) @@ -145,8 +152,8 @@ 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. +pigs, pigpiod_if, and pigpiod_if2 will need minor mods to +reflect the Windows/Mac socket interface. DOCUMENTATION @@ -160,6 +167,7 @@ man pig2vcd man pigpio man pigpiod_if +man pigpiod_if2 pydoc pigpio diff --git a/command.c b/command.c index 49ac7c6..6bd6fae 100644 --- a/command.c +++ b/command.c @@ -556,7 +556,7 @@ int cmdParse( char *p8; int32_t *p32; char c; - uint32_t tp1, tp2, tp3; + uint32_t tp1=0, tp2=0, tp3=0; int8_t to1, to2, to3; int eaten; diff --git a/pig2vcd.1 b/pig2vcd.1 index 65fab37..492ec68 100644 --- a/pig2vcd.1 +++ b/pig2vcd.1 @@ -2,7 +2,7 @@ ." Process this file with ." groff -man -Tascii pig2vcd.1 ." -.TH pig2vcd 1 2012-2014 Linux "pigpio archive" +.TH pig2vcd 1 2012-2015 Linux "pigpio archive" .SH NAME pig2vd - A utility to convert pigpio notifications to VCD. @@ -236,7 +236,7 @@ The state lines contain the new state followed by the gpio identifier. .SH SEE ALSO -pigpiod(1), pigs(1), pigpio(3), pigpiod_if(3) +pigpiod(1), pigs(1), pigpio(3), pigpiod_if(3), pigpiod_if2(3) .SH AUTHOR joan@abyz.co.uk diff --git a/pigpio.3 b/pigpio.3 index c06b3de..52ff01e 100644 --- a/pigpio.3 +++ b/pigpio.3 @@ -2,13 +2,16 @@ ." Process this file with ." groff -man -Tascii pigpio.3 ." -.TH pigpio 3 2012-2014 Linux "pigpio archive" +.TH pigpio 3 2012-2015 Linux "pigpio archive" .SH NAME pigpio - A C library to manipulate the Pi's gpios. .SH SYNOPSIS -gcc -o prog prog.c -lpigpio -lrt -lpthread +#include + + +gcc -Wall -pthread -o prog prog.c -lpigpio -lrt sudo ./prog .SH DESCRIPTION @@ -130,7 +133,7 @@ run the executable. .br .EX -gcc -o prog prog.c -lpigpio -lpthread -lrt +gcc -Wall -pthread -o prog prog.c -lpigpio -lrt .br sudo ./prog .br @@ -2411,23 +2414,23 @@ of the function description. The following abbreviations are used. .br .EX -S (1 bit) : Start bit +S (1 bit) : Start bit .br -P (1 bit) : Stop bit +P (1 bit) : Stop bit .br -Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. +Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. .br -A, NA (1 bit) : Accept and not accept bit. +A, NA (1 bit) : Accept and not accept bit. .br .br .br -Addr (7 bits): I2C 7 bit address. +Addr (7 bits): I2C 7 bit address. .br -Comm (8 bits): Command byte, a data byte which often selects a register. +i2cReg (8 bits): Command byte, a byte which often selects a register. .br -Data (8 bits): A data byte. +Data (8 bits): A data byte. .br -Count (8 bits): A data byte containing the length of a block operation. +Count (8 bits): A byte defining the length of a block operation. .br .br @@ -2484,7 +2487,7 @@ PI_I2C_WRITE_FAILED. Quick command. SMBus 2.0 5.5.1 .EX -S Addr Rd/Wr [A] P +S Addr bit [A] P .br .EE @@ -2517,7 +2520,7 @@ PI_I2C_WRITE_FAILED. Send byte. SMBus 2.0 5.5.2 .EX -S Addr Wr [A] Data [A] P +S Addr Wr [A] bVal [A] P .br .EE @@ -2584,7 +2587,7 @@ PI_I2C_WRITE_FAILED. Write byte. SMBus 2.0 5.5.4 .EX -S Addr Wr [A] Comm [A] Data [A] P +S Addr Wr [A] i2cReg [A] bVal [A] P .br .EE @@ -2620,7 +2623,7 @@ PI_I2C_WRITE_FAILED. Write word. SMBus 2.0 5.5.4 .EX -S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P +S Addr Wr [A] i2cReg [A] wValLow [A] wValHigh [A] P .br .EE @@ -2654,7 +2657,7 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. Read byte. SMBus 2.0 5.5.5 .EX -S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P +S Addr Wr [A] i2cReg [A] S Addr Rd [A] [Data] NA P .br .EE @@ -2688,7 +2691,7 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. Read word. SMBus 2.0 5.5.5 .EX -S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P +S Addr Wr [A] i2cReg [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P .br .EE @@ -2724,7 +2727,7 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. Process call. SMBus 2.0 5.5.6 .EX -S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] +S Addr Wr [A] i2cReg [A] wValLow [A] wValHigh [A] .br S Addr Rd [A] [DataLow] A [DataHigh] NA P .br @@ -2764,7 +2767,9 @@ PI_I2C_WRITE_FAILED. Block write. SMBus 2.0 5.5.7 .EX -S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P +S Addr Wr [A] i2cReg [A] count [A] +.br + buf0 [A] buf1 [A] ... [A] bufn [A] P .br .EE @@ -2805,9 +2810,9 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. Block read. SMBus 2.0 5.5.7 .EX -S Addr Wr [A] Comm [A] +S Addr Wr [A] i2cReg [A] .br - S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P + S Addr Rd [A] [Count] A [buf0] A [buf1] A ... A [bufn] NA P .br .EE @@ -2853,9 +2858,9 @@ bytes sent/received must be 32 or less. Block write-block read. SMBus 2.0 5.5.8 .EX -S Addr Wr [A] Comm [A] Count [A] Data [A] ... +S Addr Wr [A] i2cReg [A] count [A] buf0 [A] ... bufn [A] .br - S Addr Rd [A] [Count] A [Data] ... A P + S Addr Rd [A] [Count] A [buf0] A ... [bufn] A P .br .EE @@ -2892,9 +2897,9 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. .br .EX -S Addr Wr [A] Comm [A] +S Addr Wr [A] i2cReg [A] .br - S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P + S Addr Rd [A] [buf0] A [buf1] A ... A [bufn] NA P .br .EE @@ -2931,7 +2936,7 @@ PI_I2C_WRITE_FAILED. .br .EX -S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P +S Addr Wr [A] i2cReg [A] buf0 [A] buf1 [A] ... [A] bufn [A] P .br .EE @@ -2960,6 +2965,16 @@ handle: >=0, as returned by a call to \fBi2cOpen\fP Returns count (>0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_READ_FAILED. +.br + +.br + +.EX +S Addr Rd [A] [buf0] A [buf1] A ... A [bufn] NA P +.br + +.EE + .IP "\fBint i2cWriteDevice(unsigned handle, char *buf, unsigned count)\fP" .IP "" 4 This writes count bytes from buf to the raw device. @@ -2984,6 +2999,16 @@ handle: >=0, as returned by a call to \fBi2cOpen\fP Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. +.br + +.br + +.EX +S Addr Wr [A] buf0 [A] buf1 [A] ... [A] bufn [A] P +.br + +.EE + .IP "\fBvoid i2cSwitchCombined(int setting)\fP" .IP "" 4 This sets the I2C (i2c-bcm2708) module "use combined transactions" @@ -4130,7 +4155,7 @@ registered per timer. .br See \fBgpioSetTimerFunc\fP for further details. -.IP "\fBpthread_t *gpioStartThread(gpioThreadFunc_t f, void *arg)\fP" +.IP "\fBpthread_t *gpioStartThread(gpioThreadFunc_t f, void *userdata)\fP" .IP "" 4 Starts a new thread of execution with f as the main routine. @@ -4139,9 +4164,9 @@ Starts a new thread of execution with f as the main routine. .br .EX - f: the main function for the new thread + f: the main function for the new thread .br -arg: a pointer to arbitrary user data +userdata: a pointer to arbitrary user data .br .EE @@ -5706,17 +5731,6 @@ a stable level). .br -.IP "\fB*arg\fP" 0 - -.br - -.br -A pointer to a void object passed to a thread started by gpioStartThread. - -.br - -.br - .IP "\fBarg1\fP" 0 .br @@ -7410,6 +7424,48 @@ A pointer to arbitrary user data. This may be used to identify the instance. .br +.br +You must ensure that the pointer is in scope at the time it is processed. If +it is a pointer to a global this is automatic. Do not pass the address of a +local variable. If you want to pass a transient object then use the +following technique. + +.br + +.br +In the calling function: + +.br + +.br +user_type *userdata; +.br +user_type my_userdata; + +.br + +.br +userdata = malloc(sizeof(user_type)); +.br +*userdata = my_userdata; + +.br + +.br +In the receiving function: + +.br + +.br +user_type my_userdata = *(user_type*)userdata; + +.br + +.br +free(userdata); + +.br + .br .IP "\fBvoid\fP" 0 @@ -8026,7 +8082,7 @@ A 16-bit word value. .SH SEE ALSO -pigpiod(1), pig2vcd(1), pigs(1), pigpiod_if(3) +pigpiod(1), pig2vcd(1), pigs(1), pigpiod_if(3), pigpiod_if2(3) .SH AUTHOR joan@abyz.co.uk diff --git a/pigpio.c b/pigpio.c index 3205f2c..cf10699 100644 --- a/pigpio.c +++ b/pigpio.c @@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to */ -/* pigpio version 39 */ +/* pigpio version 40 */ /* include ------------------------------------------------------- */ @@ -1375,6 +1375,8 @@ static void initDMAgo(volatile uint32_t *dmaAddr, uint32_t cbAddr); int gpioWaveTxStart(unsigned wave_mode); /* deprecated */ +static void closeOrphanedNotifications(int slot, int fd); + /* ======================================================================= */ @@ -5394,6 +5396,7 @@ static void * pthAlertThread(void *x) { if (gpioNotify[n].pipe) { + DBG(DBG_INTERNAL, "close notify pipe %d", gpioNotify[n].fd); close(gpioNotify[n].fd); sprintf(fifo, "/dev/pigpio%d", n); @@ -5499,6 +5502,8 @@ static void * pthAlertThread(void *x) if (emit) { + DBG(DBG_FAST_TICK, "notification %d (%d reports, %x-%x)", + n, emit, gpioReport[0].seqno, gpioReport[emit-1].seqno); gpioNotify[n].lastReportTick = stick; max_emits = gpioNotify[n].max_emits; @@ -6221,7 +6226,10 @@ static void *pthSocketThreadHandler(void *fdC) if (recv(sock, buf, p[3], MSG_WAITALL) != p[3]) { /* Serious error. No point continuing. */ - DBG(DBG_ALWAYS, "recv failed for %d bytes", p[3]); + DBG(DBG_ALWAYS, + "recv failed for %d bytes, sock=%d", p[3], sock); + + closeOrphanedNotifications(-1, sock); close(sock); @@ -6231,7 +6239,10 @@ static void *pthSocketThreadHandler(void *fdC) else { /* Serious error. No point continuing. */ - DBG(DBG_ALWAYS, "ext too large %d(%d)", p[3], sizeof(buf)); + DBG(DBG_ALWAYS, + "ext too large %d(%d), sock=%d", p[3], sizeof(buf), sock); + + closeOrphanedNotifications(-1, sock); close(sock); @@ -6299,6 +6310,8 @@ static void *pthSocketThreadHandler(void *fdC) } } + closeOrphanedNotifications(-1, sock); + close(sock); return 0; @@ -6340,6 +6353,8 @@ static void * pthSocketThread(void *x) { pthread_t thr; + closeOrphanedNotifications(-1, fdC); + sock = malloc(sizeof(int)); *sock = fdC; @@ -7123,6 +7138,16 @@ static void initReleaseResources(void) /* shut down running threads */ + for (i=0; i<=PI_MAX_USER_GPIO; i++) + { + if (gpioISR[i].pth) + { + /* destroy thread, unexport GPIO */ + + gpioSetISRFunc(i, 0, 0, NULL); + } + } + for (i=0; i<=PI_MAX_TIMER; i++) { if (gpioTimer[i].running) @@ -10026,6 +10051,24 @@ int gpioSetISRFuncEx( return intGpioSetISRFunc(gpio, edge, timeout, f, 1, userdata); } +static void closeOrphanedNotifications(int slot, int fd) +{ + int i; + + /* Check for and close any orphaned notifications. */ + + for (i=0; i #include #include -#define PIGPIO_VERSION 39 +#define PIGPIO_VERSION 40 /*TEXT @@ -83,7 +83,7 @@ Assuming your source is in prog.c use the following command to build and run the executable. . . -gcc -o prog prog.c -lpigpio -lpthread -lrt +gcc -Wall -pthread -o prog prog.c -lpigpio -lrt sudo ./prog . . @@ -2034,14 +2034,14 @@ For the SMBus commands the low level transactions are shown at the end of the function description. The following abbreviations are used. . . -S (1 bit) : Start bit -P (1 bit) : Stop bit -Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. -A, NA (1 bit) : Accept and not accept bit. -Addr (7 bits): I2C 7 bit address. -Comm (8 bits): Command byte, a data byte which often selects a register. -Data (8 bits): A data byte. -Count (8 bits): A data byte containing the length of a block operation. +S (1 bit) : Start bit +P (1 bit) : Stop bit +Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. +A, NA (1 bit) : Accept and not accept bit. +Addr (7 bits): I2C 7 bit address. +i2cReg (8 bits): Command byte, a byte which often selects a register. +Data (8 bits): A data byte. +Count (8 bits): A byte defining the length of a block operation. [..]: Data sent by the device. . . @@ -2077,7 +2077,7 @@ PI_I2C_WRITE_FAILED. Quick command. SMBus 2.0 5.5.1 . . -S Addr Rd/Wr [A] P +S Addr bit [A] P . . D*/ @@ -2097,7 +2097,7 @@ PI_I2C_WRITE_FAILED. Send byte. SMBus 2.0 5.5.2 . . -S Addr Wr [A] Data [A] P +S Addr Wr [A] bVal [A] P . . D*/ @@ -2138,7 +2138,7 @@ PI_I2C_WRITE_FAILED. Write byte. SMBus 2.0 5.5.4 . . -S Addr Wr [A] Comm [A] Data [A] P +S Addr Wr [A] i2cReg [A] bVal [A] P . . D*/ @@ -2160,7 +2160,7 @@ PI_I2C_WRITE_FAILED. Write word. SMBus 2.0 5.5.4 . . -S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P +S Addr Wr [A] i2cReg [A] wValLow [A] wValHigh [A] P . . D*/ @@ -2181,7 +2181,7 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. Read byte. SMBus 2.0 5.5.5 . . -S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P +S Addr Wr [A] i2cReg [A] S Addr Rd [A] [Data] NA P . . D*/ @@ -2202,7 +2202,7 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. Read word. SMBus 2.0 5.5.5 . . -S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P +S Addr Wr [A] i2cReg [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P . . D*/ @@ -2224,7 +2224,7 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. Process call. SMBus 2.0 5.5.6 . . -S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] +S Addr Wr [A] i2cReg [A] wValLow [A] wValHigh [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P . . D*/ @@ -2249,7 +2249,8 @@ PI_I2C_WRITE_FAILED. Block write. SMBus 2.0 5.5.7 . . -S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P +S Addr Wr [A] i2cReg [A] count [A] + buf0 [A] buf1 [A] ... [A] bufn [A] P . . D*/ @@ -2273,8 +2274,8 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. Block read. SMBus 2.0 5.5.7 . . -S Addr Wr [A] Comm [A] - S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P +S Addr Wr [A] i2cReg [A] + S Addr Rd [A] [Count] A [buf0] A [buf1] A ... A [bufn] NA P . . D*/ @@ -2303,8 +2304,8 @@ bytes sent/received must be 32 or less. Block write-block read. SMBus 2.0 5.5.8 . . -S Addr Wr [A] Comm [A] Count [A] Data [A] ... - S Addr Rd [A] [Count] A [Data] ... A P +S Addr Wr [A] i2cReg [A] count [A] buf0 [A] ... bufn [A] + S Addr Rd [A] [Count] A [buf0] A ... [bufn] A P . . D*/ @@ -2327,8 +2328,8 @@ Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_READ_FAILED. . . -S Addr Wr [A] Comm [A] - S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P +S Addr Wr [A] i2cReg [A] + S Addr Rd [A] [buf0] A [buf1] A ... A [bufn] NA P . . D*/ @@ -2351,7 +2352,7 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. . . -S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P +S Addr Wr [A] i2cReg [A] buf0 [A] buf1 [A] ... [A] bufn [A] P . . D*/ @@ -2368,6 +2369,10 @@ handle: >=0, as returned by a call to [*i2cOpen*] Returns count (>0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +. . +S Addr Rd [A] [buf0] A [buf1] A ... A [bufn] NA P +. . D*/ @@ -2384,6 +2389,10 @@ handle: >=0, as returned by a call to [*i2cOpen*] Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. + +. . +S Addr Wr [A] buf0 [A] buf1 [A] ... [A] bufn [A] P +. . D*/ /*F*/ @@ -3046,13 +3055,13 @@ D*/ /*F*/ -pthread_t *gpioStartThread(gpioThreadFunc_t f, void *arg); +pthread_t *gpioStartThread(gpioThreadFunc_t f, void *userdata); /*D Starts a new thread of execution with f as the main routine. . . - f: the main function for the new thread -arg: a pointer to arbitrary user data + f: the main function for the new thread +userdata: a pointer to arbitrary user data . . Returns a pointer to pthread_t if OK, otherwise NULL. @@ -4005,10 +4014,6 @@ The number of microseconds level changes are reported for once a noise filter has been triggered (by [*steady*] microseconds of a stable level). -*arg:: - -A pointer to a void object passed to a thread started by gpioStartThread. - arg1:: An unsigned argument passed to a user customised function. Its @@ -4717,6 +4722,25 @@ See [*gpio*]. A pointer to arbitrary user data. This may be used to identify the instance. +You must ensure that the pointer is in scope at the time it is processed. If +it is a pointer to a global this is automatic. Do not pass the address of a +local variable. If you want to pass a transient object then use the +following technique. + +In the calling function: + +user_type *userdata; +user_type my_userdata; + +userdata = malloc(sizeof(user_type)); +*userdata = my_userdata; + +In the receiving function: + +user_type my_userdata = *(user_type*)userdata; + +free(userdata); + void:: Denoting no parameter is required diff --git a/pigpio.py b/pigpio.py index 965d9b7..e8587d7 100644 --- a/pigpio.py +++ b/pigpio.py @@ -269,7 +269,7 @@ import threading import os import atexit -VERSION = "1.23" +VERSION = "1.24" exceptions = True @@ -2190,9 +2190,9 @@ class pi(): Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. A, NA (1 bit) : Accept and not accept bit. Addr (7 bits): I2C 7 bit address. - Comm (8 bits): Command byte, which often selects a register. + reg (8 bits): Command byte, which often selects a register. Data (8 bits): A data byte. - Count (8 bits): A byte containing the length of a block operation. + Count (8 bits): A byte defining the length of a block operation. [..]: Data sent by the device. . . @@ -2231,7 +2231,7 @@ class pi(): SMBus 2.0 5.5.1 - Quick command. . . - S Addr Rd/Wr [A] P + S Addr bit [A] P . . ... @@ -2250,7 +2250,7 @@ class pi(): SMBus 2.0 5.5.2 - Send byte. . . - S Addr Wr [A] Data [A] P + S Addr Wr [A] byte_val [A] P . . ... @@ -2289,7 +2289,7 @@ class pi(): SMBus 2.0 5.5.4 - Write byte. . . - S Addr Wr [A] Comm [A] Data [A] P + S Addr Wr [A] reg [A] byte_val [A] P . . ... @@ -2320,7 +2320,7 @@ class pi(): SMBus 2.0 5.5.4 - Write word. . . - S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P + S Addr Wr [A] reg [A] word_val_Low [A] word_val_High [A] P . . ... @@ -2350,7 +2350,7 @@ class pi(): SMBus 2.0 5.5.5 - Read byte. . . - S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P + S Addr Wr [A] reg [A] S Addr Rd [A] [Data] NA P . . ... @@ -2373,7 +2373,7 @@ class pi(): SMBus 2.0 5.5.5 - Read word. . . - S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P + S Addr Wr [A] reg [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P . . ... @@ -2397,7 +2397,7 @@ class pi(): SMBus 2.0 5.5.6 - Process call. . . - S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] + S Addr Wr [A] reg [A] word_val_Low [A] word_val_High [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P . . @@ -2426,8 +2426,8 @@ class pi(): SMBus 2.0 5.5.7 - Block write. . . - S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] - Data [A] P + S Addr Wr [A] reg [A] len(data) [A] data0 [A] data1 [A] ... [A] + datan [A] P . . ... @@ -2461,7 +2461,7 @@ class pi(): SMBus 2.0 5.5.7 - Block read. . . - S Addr Wr [A] Comm [A] + S Addr Wr [A] reg [A] S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P . . @@ -2505,7 +2505,7 @@ class pi(): SMBus 2.0 5.5.8 - Block write-block read. . . - S Addr Wr [A] Comm [A] Count [A] Data [A] ... + S Addr Wr [A] reg [A] len(data) [A] data0 [A] ... datan [A] S Addr Rd [A] [Count] A [Data] ... A P . . @@ -2550,8 +2550,7 @@ class pi(): data:= the bytes to write. . . - S Addr Wr [A] Comm [A] - S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P + S Addr Wr [A] reg [A] data0 [A] data1 [A] ... [A] datan [NA] P . . ... @@ -2585,7 +2584,8 @@ class pi(): count:= >0, the number of bytes to read. . . - S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P + S Addr Wr [A] reg [A] + S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P . . The returned value is a tuple of the number of bytes read and a @@ -2626,6 +2626,10 @@ class pi(): handle:= >=0 (as returned by a prior call to [*i2c_open*]). count:= >0, the number of bytes to read. + . . + S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P + . . + The returned value is a tuple of the number of bytes read and a bytearray containing the bytes. If there was an error the number of bytes read will be less than zero (and will contain @@ -2652,6 +2656,10 @@ class pi(): handle:= >=0 (as returned by a prior call to [*i2c_open*]). data:= the bytes to write. + . . + S Addr Wr [A] data0 [A] data1 [A] ... [A] datan [A] P + . . + ... pi.i2c_write_device(h, b"\\x12\\x34\\xA8") @@ -3902,7 +3910,9 @@ def xref(): PI_CHAIN_NESTING = -118 PI_CHAIN_TOO_BIG = -119 PI_DEPRECATED = -120 - PI_BAD_SER_INVERT = -121 + PI_BAD_SER_INVERT = -121 + PI_BAD_FOREVER = -124 + PI_BAD_FILTER = -125 . . frequency: 0-40000 diff --git a/pigpiod.1 b/pigpiod.1 index a54d7b6..ef04989 100644 --- a/pigpiod.1 +++ b/pigpiod.1 @@ -2,7 +2,7 @@ ." Process this file with ." groff -man -Tascii pigpiod.1 ." -.TH pigpiod 1 2012-2014 Linux "pigpio archive" +.TH pigpiod 1 2012-2015 Linux "pigpio archive" .SH NAME pigpiod - A utility to start the pigpio library as a daemon. @@ -183,7 +183,7 @@ The high USB power mode gpio may be written (gpio 38 for type 3 boards). .SH SEE ALSO -pig2vcd(1), pigs(1), pigpio(3), pigpiod_if(3) +pig2vcd(1), pigs(1), pigpio(3), pigpiod_if(3), pigpiod_if2(3) .SH AUTHOR joan@abyz.co.uk diff --git a/pigpiod_if.3 b/pigpiod_if.3 index fac7b70..6cb1b27 100644 --- a/pigpiod_if.3 +++ b/pigpiod_if.3 @@ -2,18 +2,27 @@ ." Process this file with ." groff -man -Tascii pigpiod_if.3 ." -.TH pigpiod_if 3 2012-2014 Linux "pigpio archive" +.TH pigpiod_if 3 2012-2015 Linux "pigpio archive" .SH NAME pigpiod_if - A C library to interface to the pigpio daemon. .SH SYNOPSIS -gcc -o prog prog.c -lpigpiod_if +#include + + +gcc -Wall -pthread -o prog prog.c -lpigpiod_if -lrt ./prog .SH DESCRIPTION +.br + +.br +THIS LIBRARY IS DEPRECATED. NEW CODE SHOULD BE WRITTEN TO +USE THE MORE VERSATILE pigpiod_if2 LIBRARY. + .br .br @@ -122,7 +131,7 @@ Assuming your source is in prog.c use the following command to build .br .EX -gcc -o prog prog.c -lpigpiod_if +gcc -Wall -pthread -o prog prog.c -lpigpiod_if -lrt .br .EE @@ -4770,7 +4779,7 @@ typedef enum .SH SEE ALSO -pigpiod(1), pig2vcd(1), pigs(1), pigpio(3) +pigpiod(1), pig2vcd(1), pigs(1), pigpio(3), pigpiod_if2(3) .SH AUTHOR joan@abyz.co.uk diff --git a/pigpiod_if.h b/pigpiod_if.h index b819464..7bafcdb 100644 --- a/pigpiod_if.h +++ b/pigpiod_if.h @@ -34,6 +34,9 @@ For more information, please refer to /*TEXT +THIS LIBRARY IS DEPRECATED. NEW CODE SHOULD BE WRITTEN TO +USE THE MORE VERSATILE pigpiod_if2 LIBRARY. + pigpiod_if is a C library for the Raspberry which allows control of the gpios via the socket interface to the pigpio daemon. @@ -78,7 +81,7 @@ Include in your source files. Assuming your source is in prog.c use the following command to build . . -gcc -o prog prog.c -lpigpiod_if +gcc -Wall -pthread -o prog prog.c -lpigpiod_if -lrt . . to run make sure the pigpio daemon is running diff --git a/pigpiod_if2.3 b/pigpiod_if2.3 new file mode 100644 index 0000000..3015610 --- /dev/null +++ b/pigpiod_if2.3 @@ -0,0 +1,5240 @@ + +." Process this file with +." groff -man -Tascii pigpiod_if2.3 +." +.TH pigpiod_if2 3 2012-2015 Linux "pigpio archive" +.SH NAME +pigpiod_if2 - A C library to interface to the pigpio daemon. + +.SH SYNOPSIS + +#include + + +gcc -Wall -pthread -o prog prog.c -lpigpiod_if2 -lrt + + ./prog +.SH DESCRIPTION + + +.br + +.br +pigpiod_if2 is a C library for the Raspberry which allows control +of the gpios via the socket interface to the pigpio daemon. +.br + +.br + +.br +.SS Features +.br + +.br +o PWM on any of gpios 0-31 + +.br + +.br +o servo pulses on any of gpios 0-31 + +.br + +.br +o callbacks when any of gpios 0-31 change state + +.br + +.br +o callbacks at timed intervals + +.br + +.br +o reading/writing all of the gpios in a bank as one operation + +.br + +.br +o individually setting gpio modes, reading and writing + +.br + +.br +o notifications when any of gpios 0-31 change state + +.br + +.br +o the construction of output waveforms with microsecond timing + +.br + +.br +o rudimentary permission control over gpios + +.br + +.br +o a simple interface to start and stop new threads + +.br + +.br +o I2C, SPI, and serial link wrappers + +.br + +.br +o creating and running scripts on the pigpio daemon + +.br + +.br +.SS gpios +.br + +.br +ALL gpios are identified by their Broadcom number. + +.br + +.br +.SS Notes +.br + +.br +The PWM and servo pulses are timed using the DMA and PWM/PCM peripherals. + +.br + +.br +.SS Usage +.br + +.br +Include in your source files. + +.br + +.br +Assuming your source is in prog.c use the following command to build + +.br + +.br + +.EX +gcc -Wall -pthread -o prog prog.c -lpigpiod_if2 -lrt +.br + +.EE + +.br + +.br +to run make sure the pigpio daemon is running + +.br + +.br + +.EX +sudo pigpiod +.br + +.br + ./prog # sudo is not required to run programs linked to pigpiod_if2 +.br + +.EE + +.br + +.br +For examples see x_pigpiod_if2.c within the pigpio archive file. + +.br + +.br +.SS Notes +.br + +.br +All the functions which return an int return < 0 on error + +.br + +.br +.SH FUNCTIONS + +.IP "\fBdouble time_time(void)\fP" +.IP "" 4 +Return the current time in seconds since the Epoch. + +.IP "\fBvoid time_sleep(double seconds)\fP" +.IP "" 4 +Delay execution for a given number of seconds. + +.br + +.br + +.EX +seconds: the number of seconds to delay. +.br + +.EE + +.IP "\fBchar *pigpio_error(int errnum)\fP" +.IP "" 4 +Return a text description for an error code. + +.br + +.br + +.EX +errnum: the error code. +.br + +.EE + +.IP "\fBunsigned pigpiod_if_version(void)\fP" +.IP "" 4 +Return the pigpiod_if2 version. + +.IP "\fBpthread_t *start_thread(gpioThreadFunc_t thread_func, void *userdata)\fP" +.IP "" 4 +Starts a new thread of execution with thread_func as the main routine. + +.br + +.br + +.EX +thread_func: the main function for the new thread. +.br + userdata: a pointer to an arbitrary argument. +.br + +.EE + +.br + +.br +Returns a pointer to pthread_t if OK, otherwise NULL. + +.br + +.br +The function is passed the single argument userdata. + +.br + +.br +The thread can be cancelled by passing the pointer to pthread_t to +\fBstop_thread\fP. + +.IP "\fBvoid stop_thread(pthread_t *pth)\fP" +.IP "" 4 +Cancels the thread pointed at by pth. + +.br + +.br + +.EX +pth: the thread to be stopped. +.br + +.EE + +.br + +.br +No value is returned. + +.br + +.br +The thread to be stopped should have been started with \fBstart_thread\fP. + +.IP "\fBint pigpio_start(char *addrStr, char *portStr)\fP" +.IP "" 4 +Connect to the pigpio daemon. Reserving command and +notification streams. + +.br + +.br + +.EX +addrStr: specifies the host or IP address of the Pi running the +.br + pigpio daemon. It may be NULL in which case localhost +.br + is used unless overridden by the PIGPIO_ADDR environment +.br + variable. +.br + +.br +portStr: specifies the port address used by the Pi running the +.br + pigpio daemon. It may be NULL in which case "8888" +.br + is used unless overridden by the PIGPIO_PORT environment +.br + variable. +.br + +.EE + +.br + +.br +Returns an integer value greater than or equal to zero if OK. + +.br + +.br +This value is passed to the GPIO routines to specify the Pi +to be operated on. + +.IP "\fBvoid pigpio_stop(int pi)\fP" +.IP "" 4 +Terminates the connection to a pigpio daemon and releases +resources used by the library. + +.br + +.br + +.EX +pi: 0- (as returned by \fBpigpio_start\fP). +.br + +.EE + +.IP "\fBint set_mode(int pi, unsigned gpio, unsigned mode)\fP" +.IP "" 4 +Set the gpio mode. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +gpio: 0-53. +.br +mode: PI_INPUT, PI_OUTPUT, PI_ALT0, _ALT1, +.br + PI_ALT2, PI_ALT3, PI_ALT4, PI_ALT5. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_MODE, +or PI_NOT_PERMITTED. + +.IP "\fBint get_mode(int pi, unsigned gpio)\fP" +.IP "" 4 +Get the gpio mode. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +gpio: 0-53. +.br + +.EE + +.br + +.br +Returns the gpio mode if OK, otherwise PI_BAD_GPIO. + +.IP "\fBint set_pull_up_down(int pi, unsigned gpio, unsigned pud)\fP" +.IP "" 4 +Set or clear the gpio pull-up/down resistor. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +gpio: 0-53. +.br + pud: PI_PUD_UP, PI_PUD_DOWN, PI_PUD_OFF. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_PUD, +or PI_NOT_PERMITTED. + +.IP "\fBint gpio_read(int pi, unsigned gpio)\fP" +.IP "" 4 +Read the gpio level. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +gpio:0-53. +.br + +.EE + +.br + +.br +Returns the gpio level if OK, otherwise PI_BAD_GPIO. + +.IP "\fBint gpio_write(int pi, unsigned gpio, unsigned level)\fP" +.IP "" 4 +Write the gpio level. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + gpio: 0-53. +.br +level: 0, 1. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_LEVEL, +or PI_NOT_PERMITTED. + +.br + +.br +Notes + +.br + +.br +If PWM or servo pulses are active on the gpio they are switched off. + +.IP "\fBint set_PWM_dutycycle(int pi, unsigned user_gpio, unsigned dutycycle)\fP" +.IP "" 4 +Start (non-zero dutycycle) or stop (0) PWM pulses on the gpio. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br +dutycycle: 0-range (range defaults to 255). +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_DUTYCYCLE, +or PI_NOT_PERMITTED. +Notes + +.br + +.br +The \fBset_PWM_range\fP function may be used to change the +default range of 255. + +.IP "\fBint get_PWM_dutycycle(int pi, unsigned user_gpio)\fP" +.IP "" 4 +Return the PWM dutycycle in use on a gpio. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO or PI_NOT_PWM_GPIO. + +.br + +.br +For normal PWM the dutycycle will be out of the defined range +for the gpio (see \fBget_PWM_range\fP). + +.br + +.br +If a hardware clock is active on the gpio the reported dutycycle +will be 500000 (500k) out of 1000000 (1M). + +.br + +.br +If hardware PWM is active on the gpio the reported dutycycle +will be out of a 1000000 (1M). + +.IP "\fBint set_PWM_range(int pi, unsigned user_gpio, unsigned range)\fP" +.IP "" 4 +Set the range of PWM values to be used on the gpio. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + range: 25-40000. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_DUTYRANGE, +or PI_NOT_PERMITTED. + +.br + +.br +Notes + +.br + +.br +If PWM is currently active on the gpio its dutycycle will be +scaled to reflect the new range. + +.br + +.br +The real range, the number of steps between fully off and fully on +for each of the 18 available gpio frequencies is + +.br + +.br + +.EX + 25(#1), 50(#2), 100(#3), 125(#4), 200(#5), 250(#6), +.br + 400(#7), 500(#8), 625(#9), 800(#10), 1000(#11), 1250(#12), +.br +2000(#13), 2500(#14), 4000(#15), 5000(#16), 10000(#17), 20000(#18) +.br + +.EE + +.br + +.br +The real value set by set_PWM_range is (dutycycle * real range) / range. + +.IP "\fBint get_PWM_range(int pi, unsigned user_gpio)\fP" +.IP "" 4 +Get the range of PWM values being used on the gpio. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + +.EE + +.br + +.br +Returns the dutycycle range used for the gpio if OK, +otherwise PI_BAD_USER_GPIO. + +.br + +.br +If a hardware clock or hardware PWM is active on the gpio the +reported range will be 1000000 (1M). + +.IP "\fBint get_PWM_real_range(int pi, unsigned user_gpio)\fP" +.IP "" 4 +Get the real underlying range of PWM values being used on the gpio. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + +.EE + +.br + +.br +Returns the real range used for the gpio if OK, +otherwise PI_BAD_USER_GPIO. + +.br + +.br +If a hardware clock is active on the gpio the reported +real range will be 1000000 (1M). + +.br + +.br +If hardware PWM is active on the gpio the reported real range +will be approximately 250M divided by the set PWM frequency. + +.br + +.br + +.IP "\fBint set_PWM_frequency(int pi, unsigned user_gpio, unsigned frequency)\fP" +.IP "" 4 +Set the frequency (in Hz) of the PWM to be used on the gpio. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br +frequency: 0- (Hz). +.br + +.EE + +.br + +.br +Returns the numerically closest frequency if OK, otherwise +PI_BAD_USER_GPIO or PI_NOT_PERMITTED. + +.br + +.br +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. + +.br + +.br +Each gpio can be independently set to one of 18 different +PWM frequencies. + +.br + +.br +If PWM is currently active on the gpio it will be switched +off and then back on at the new frequency. + +.br + +.br + +.EX +1us 40000, 20000, 10000, 8000, 5000, 4000, 2500, 2000, 1600, +.br + 1250, 1000, 800, 500, 400, 250, 200, 100, 50 +.br + +.br +2us 20000, 10000, 5000, 4000, 2500, 2000, 1250, 1000, 800, +.br + 625, 500, 400, 250, 200, 125, 100, 50 , 25 +.br + +.br +4us 10000, 5000, 2500, 2000, 1250, 1000, 625, 500, 400, +.br + 313, 250, 200, 125, 100, 63, 50, 25, 13 +.br + +.br +5us 8000, 4000, 2000, 1600, 1000, 800, 500, 400, 320, +.br + 250, 200, 160, 100 , 80, 50, 40, 20, 10 +.br + +.br +8us 5000, 2500, 1250, 1000, 625, 500, 313, 250, 200, +.br + 156, 125, 100, 63, 50, 31, 25, 13, 6 +.br + +.br +10us 4000, 2000, 1000, 800, 500, 400, 250, 200, 160, +.br + 125, 100, 80, 50, 40, 25, 20, 10, 5 +.br + +.EE + +.IP "\fBint get_PWM_frequency(int pi, unsigned user_gpio)\fP" +.IP "" 4 +Get the frequency of PWM being used on the gpio. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + +.EE + +.br + +.br +For normal PWM the frequency will be that defined for the gpio by +\fBset_PWM_frequency\fP. + +.br + +.br +If a hardware clock is active on the gpio the reported frequency +will be that set by \fBhardware_clock\fP. + +.br + +.br +If hardware PWM is active on the gpio the reported frequency +will be that set by \fBhardware_PWM\fP. + +.br + +.br +Returns the frequency (in hertz) used for the gpio if OK, +otherwise PI_BAD_USER_GPIO. + +.IP "\fBint set_servo_pulsewidth(int pi, unsigned user_gpio, unsigned pulsewidth)\fP" +.IP "" 4 +Start (500-2500) or stop (0) servo pulses on the gpio. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + user_gpio: 0-31. +.br +pulsewidth: 0 (off), 500 (anti-clockwise) - 2500 (clockwise). +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_PULSEWIDTH or +PI_NOT_PERMITTED. + +.br + +.br +The selected pulsewidth will continue to be transmitted until +changed by a subsequent call to set_servo_pulsewidth. + +.br + +.br +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. + +.br + +.br +You can DAMAGE a servo if you command it to move beyond its limits. + +.br + +.br +OTHER UPDATE RATES: + +.br + +.br +This function updates servos at 50Hz. If you wish to use a different +update frequency you will have to use the PWM functions. + +.br + +.br + +.EX +Update Rate (Hz) 50 100 200 400 500 +.br +1E6/Hz 20000 10000 5000 2500 2000 +.br + +.EE + +.br + +.br +Firstly set the desired PWM frequency using \fBset_PWM_frequency\fP. + +.br + +.br +Then set the PWM range using \fBset_PWM_range\fP to 1E6/Hz. +Doing this allows you to use units of microseconds when setting +the servo pulsewidth. + +.br + +.br +E.g. If you want to update a servo connected to gpio 25 at 400Hz + +.br + +.br + +.EX +set_PWM_frequency(25, 400); +.br +set_PWM_range(25, 2500); +.br + +.EE + +.br + +.br +Thereafter use the \fBset_PWM_dutycycle\fP function to move the servo, +e.g. set_PWM_dutycycle(25, 1500) will set a 1500 us pulse. +.br + +.IP "\fBint get_servo_pulsewidth(int pi, unsigned user_gpio)\fP" +.IP "" 4 +Return the servo pulsewidth in use on a gpio. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO or PI_NOT_SERVO_GPIO. + +.IP "\fBint notify_open(int pi)\fP" +.IP "" 4 +Get a free notification handle. + +.br + +.br + +.EX +pi: 0- (as returned by \fBpigpio_start\fP). +.br + +.EE + +.br + +.br +Returns a handle greater than or equal to zero if OK, +otherwise PI_NO_HANDLE. + +.br + +.br +A notification is a method for being notified of gpio state +changes via a pipe. + +.br + +.br +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 \fBcallback\fP +should be used instead. + +.br + +.br +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. + +.IP "\fBint notify_begin(int pi, unsigned handle, uint32_t bits)\fP" +.IP "" 4 +Start notifications on a previously opened handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: 0-31 (as returned by \fBnotify_open\fP) +.br + bits: a mask indicating the gpios to be notified. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE. + +.br + +.br +The notification sends state changes for each gpio whose +corresponding bit in bits is set. + +.br + +.br +Notes + +.br + +.br +Each notification occupies 12 bytes in the fifo as follows: + +.br + +.br + +.EX +H (16 bit) seqno +.br +H (16 bit) flags +.br +I (32 bit) tick +.br +I (32 bit) level +.br + +.EE + +.IP "\fBint notify_pause(int pi, unsigned handle)\fP" +.IP "" 4 +Pause notifications on a previously opened handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: 0-31 (as returned by \fBnotify_open\fP) +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE. + +.br + +.br +Notifications for the handle are suspended until +\fBnotify_begin\fP is called again. + +.IP "\fBint notify_close(int pi, unsigned handle)\fP" +.IP "" 4 +Stop notifications on a previously opened handle and +release the handle for reuse. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: 0-31 (as returned by \fBnotify_open\fP) +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE. + +.IP "\fBint set_watchdog(int pi, unsigned user_gpio, unsigned timeout)\fP" +.IP "" 4 +Sets a watchdog for a gpio. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + timeout: 0-60000. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO +or PI_BAD_WDOG_TIMEOUT. + +.br + +.br +The watchdog is nominally in milliseconds. + +.br + +.br +Only one watchdog may be registered per gpio. + +.br + +.br +The watchdog may be cancelled by setting timeout to 0. + +.br + +.br +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. + +.br + +.br +The \fBcallback\fP and \fBcallback_ex\fP functions interpret the flags +and will call registered callbacks for the gpio with level TIMEOUT. + +.IP "\fBint set_glitch_filter(int pi, unsigned user_gpio, unsigned steady)\fP" +.IP "" 4 +Sets a glitch filter on a gpio. + +.br + +.br +Level changes on the gpio are not reported unless the level +has been stable for at least \fBsteady\fP microseconds. The +level is then reported. Level changes of less than \fBsteady\fP +microseconds are ignored. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31 +.br + steady: 0-300000 +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER. + +.br + +.br +Note, each (stable) edge will be timestamped \fBsteady\fP microseconds +after it was first detected. + +.IP "\fBint set_noise_filter(int pi, unsigned user_gpio, unsigned steady, unsigned active)\fP" +.IP "" 4 +Sets a noise filter on a gpio. + +.br + +.br +Level changes on the gpio are ignored until a level which has +been stable for \fBsteady\fP microseconds is detected. Level changes +on the gpio are then reported for \fBactive\fP microseconds after +which the process repeats. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31 +.br + steady: 0-300000 +.br + active: 0-1000000 +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER. + +.br + +.br +Note, level changes before and after the active period may +be reported. Your software must be designed to cope with +such reports. + +.IP "\fBuint32_t read_bank_1(int pi)\fP" +.IP "" 4 +Read the levels of the bank 1 gpios (gpios 0-31). + +.br + +.br + +.EX +pi: 0- (as returned by \fBpigpio_start\fP). +.br + +.EE + +.br + +.br +The returned 32 bit integer has a bit set if the corresponding +gpio is logic 1. Gpio n has bit value (1<=0, as returned by \fBwave_create\fP. +.br + +.EE + +.br + +.br +Wave ids are allocated in order, 0, 1, 2, etc. + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_WAVE_ID. + +.IP "\fBint wave_send_once(int pi, unsigned wave_id)\fP" +.IP "" 4 +This function transmits the waveform with id wave_id. The waveform +is sent once. + +.br + +.br +NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +wave_id: >=0, as returned by \fBwave_create\fP. +.br + +.EE + +.br + +.br +Returns the number of DMA control blocks in the waveform if OK, +otherwise PI_BAD_WAVE_ID, or PI_BAD_WAVE_MODE. + +.IP "\fBint wave_send_repeat(int pi, unsigned wave_id)\fP" +.IP "" 4 +This function transmits the waveform with id wave_id. The waveform +cycles until cancelled (either by the sending of a new waveform or +by \fBwave_tx_stop\fP). + +.br + +.br +NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +wave_id: >=0, as returned by \fBwave_create\fP. +.br + +.EE + +.br + +.br +Returns the number of DMA control blocks in the waveform if OK, +otherwise PI_BAD_WAVE_ID, or PI_BAD_WAVE_MODE. + +.IP "\fBint wave_chain(int pi, char *buf, unsigned bufSize)\fP" +.IP "" 4 +This function transmits a chain of waveforms. + +.br + +.br +NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled. + +.br + +.br +The waves to be transmitted are specified by the contents of buf +which contains an ordered list of \fBwave_id\fPs and optional command +codes and related data. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + buf: pointer to the wave_ids and optional command codes +.br +bufSize: the number of bytes in buf +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_CHAIN_NESTING, PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD, PI_CHAIN_COUNTER, +PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG, or PI_BAD_WAVE_ID. + +.br + +.br +Each wave is transmitted in the order specified. A wave may +occur multiple times per chain. + +.br + +.br +A blocks of waves may be transmitted multiple times by using +the loop commands. The block is bracketed by loop start and +end commands. Loops may be nested. + +.br + +.br +Delays between waves may be added with the delay command. + +.br + +.br +The following command codes are supported: + +.br + +.br +Name Cmd & Data Meaning + +.br +Loop Start 255 0 Identify start of a wave block + +.br +Loop Repeat 255 1 x y loop x + y*256 times + +.br +Delay 255 2 x y delay x + y*256 microseconds + +.br +Loop Forever 255 3 loop forever + +.br + +.br + +.br +If present Loop Forever must be the last entry in the chain. + +.br + +.br +The code is currently dimensioned to support a chain with roughly +600 entries and 20 loop counters. + +.br + +.br +\fBExample\fP +.br + +.EX +#include +.br +#include +.br + +.br +#define WAVES 5 +.br +#define GPIO 4 +.br + +.br +int main(int argc, char *argv[]) +.br +{ +.br + int i, pi, wid[WAVES]; +.br + +.br + pi = pigpio_start(0, 0); +.br + if (pi<0) return -1; +.br + +.br + set_mode(pi, GPIO, PI_OUTPUT); +.br + +.br + for (i=0; i=0, as returned by \fBstore_script\fP. +.br + numPar: 0-10, the number of parameters. +.br + param: an array of parameters. +.br + +.EE + +.br + +.br +The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID, or +PI_TOO_MANY_PARAM + +.br + +.br +param is an array of up to 10 parameters which may be referenced in +the script as p0 to p9. + +.IP "\fBint script_status(int pi, unsigned script_id, uint32_t *param)\fP" +.IP "" 4 +This function returns the run status of a stored script as well +as the current values of parameters 0 to 9. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +script_id: >=0, as returned by \fBstore_script\fP. +.br + param: an array to hold the returned 10 parameters. +.br + +.EE + +.br + +.br +The function returns greater than or equal to 0 if OK, +otherwise PI_BAD_SCRIPT_ID. + +.br + +.br +The run status may be + +.br + +.br + +.EX +PI_SCRIPT_INITING +.br +PI_SCRIPT_HALTED +.br +PI_SCRIPT_RUNNING +.br +PI_SCRIPT_WAITING +.br +PI_SCRIPT_FAILED +.br + +.EE + +.br + +.br +The current value of script parameters 0 to 9 are returned in param. + +.IP "\fBint stop_script(int pi, unsigned script_id)\fP" +.IP "" 4 +This function stops a running script. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +script_id: >=0, as returned by \fBstore_script\fP. +.br + +.EE + +.br + +.br +The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID. + +.IP "\fBint delete_script(int pi, unsigned script_id)\fP" +.IP "" 4 +This function deletes a stored script. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +script_id: >=0, as returned by \fBstore_script\fP. +.br + +.EE + +.br + +.br +The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID. + +.IP "\fBint bb_serial_read_open(int pi, unsigned user_gpio, unsigned baud, unsigned data_bits)\fP" +.IP "" 4 +This function opens a gpio for bit bang reading of serial data. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + baud: 50-250000 +.br +data_bits: 1-32 +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, +or PI_GPIO_IN_USE. + +.br + +.br +The serial data is returned in a cyclic buffer and is read using +bb_serial_read. + +.br + +.br +It is the caller's responsibility to read data from the cyclic buffer +in a timely fashion. + +.IP "\fBint bb_serial_read(int pi, unsigned user_gpio, void *buf, size_t bufSize)\fP" +.IP "" 4 +This function copies up to bufSize bytes of data read from the +bit bang serial cyclic buffer to the buffer starting at buf. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31, previously opened with \fBbb_serial_read_open\fP. +.br + buf: an array to receive the read bytes. +.br + bufSize: 0- +.br + +.EE + +.br + +.br +Returns the number of bytes copied if OK, otherwise PI_BAD_USER_GPIO +or PI_NOT_SERIAL_GPIO. + +.br + +.br +The bytes returned for each character depend upon the number of +data bits \fBdata_bits\fP specified in the \fBbb_serial_read_open\fP command. + +.br + +.br +For \fBdata_bits\fP 1-8 there will be one byte per character. +.br +For \fBdata_bits\fP 9-16 there will be two bytes per character. +.br +For \fBdata_bits\fP 17-32 there will be four bytes per character. + +.IP "\fBint bb_serial_read_close(int pi, unsigned user_gpio)\fP" +.IP "" 4 +This function closes a gpio for bit bang reading of serial data. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31, previously opened with \fBbb_serial_read_open\fP. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SERIAL_GPIO. + +.IP "\fBint bb_serial_invert(int pi, unsigned user_gpio, unsigned invert)\fP" +.IP "" 4 +This function inverts serial logic for big bang serial reads. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31, previously opened with \fBbb_serial_read_open\fP. +.br + invert: 0-1, 1 invert, 0 normal. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_NOT_SERIAL_GPIO or PI_BAD_SER_INVERT. + +.IP "\fBint i2c_open(int pi, unsigned i2c_bus, unsigned i2c_addr, unsigned i2c_flags)\fP" +.IP "" 4 +This returns a handle for the device at address i2c_addr on bus i2c_bus. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + i2c_bus: 0-1. +.br + i2c_addr: 0x00-0x7F. +.br +i2c_flags: 0. +.br + +.EE + +.br + +.br +No flags are currently defined. This parameter should be set to zero. + +.br + +.br +Returns a handle (>=0) if OK, otherwise PI_BAD_I2C_BUS, PI_BAD_I2C_ADDR, +PI_BAD_FLAGS, PI_NO_HANDLE, or PI_I2C_OPEN_FAILED. + +.br + +.br +For the SMBus commands the low level transactions are shown at the end +of the function description. The following abbreviations are used. + +.br + +.br + +.EX +S (1 bit) : Start bit +.br +P (1 bit) : Stop bit +.br +Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. +.br +A, NA (1 bit) : Accept and not accept bit. +.br +.br +.br +Addr (7 bits): I2C 7 bit address. +.br +i2c_reg (8 bits): A byte which often selects a register. +.br +Data (8 bits): A data byte. +.br +Count (8 bits): A byte defining the length of a block operation. +.br + +.br +[..]: Data sent by the device. +.br + +.EE + +.IP "\fBint i2c_close(int pi, unsigned handle)\fP" +.IP "" 4 +This closes the I2C device associated with the handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBi2c_open\fP. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE. + +.IP "\fBint i2c_write_quick(int pi, unsigned handle, unsigned bit)\fP" +.IP "" 4 +This sends a single bit (in the Rd/Wr bit) to the device associated +with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBi2c_open\fP. +.br + bit: 0-1, the value to write. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +.br + +.br +Quick command. SMBus 2.0 5.5.1 + +.EX +S Addr bit [A] P +.br + +.EE + +.IP "\fBint i2c_write_byte(int pi, unsigned handle, unsigned bVal)\fP" +.IP "" 4 +This sends a single byte to the device associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBi2c_open\fP. +.br + bVal: 0-0xFF, the value to write. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +.br + +.br +Send byte. SMBus 2.0 5.5.2 + +.EX +S Addr Wr [A] bVal [A] P +.br + +.EE + +.IP "\fBint i2c_read_byte(int pi, unsigned handle)\fP" +.IP "" 4 +This reads a single byte from the device associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBi2c_open\fP. +.br + +.EE + +.br + +.br +Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE, +or PI_I2C_READ_FAILED. + +.br + +.br +Receive byte. SMBus 2.0 5.5.3 + +.EX +S Addr Rd [A] [Data] NA P +.br + +.EE + +.IP "\fBint i2c_write_byte_data(int pi, unsigned handle, unsigned i2c_reg, unsigned bVal)\fP" +.IP "" 4 +This writes a single byte to the specified register of the device +associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + handle: >=0, as returned by a call to \fBi2c_open\fP. +.br +i2c_reg: 0-255, the register to write. +.br + bVal: 0-0xFF, the value to write. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +.br + +.br +Write byte. SMBus 2.0 5.5.4 + +.EX +S Addr Wr [A] i2c_reg [A] bVal [A] P +.br + +.EE + +.IP "\fBint i2c_write_word_data(int pi, unsigned handle, unsigned i2c_reg, unsigned wVal)\fP" +.IP "" 4 +This writes a single 16 bit word to the specified register of the device +associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + handle: >=0, as returned by a call to \fBi2c_open\fP. +.br +i2c_reg: 0-255, the register to write. +.br + wVal: 0-0xFFFF, the value to write. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +.br + +.br +Write word. SMBus 2.0 5.5.4 + +.EX +S Addr Wr [A] i2c_reg [A] wval_Low [A] wVal_High [A] P +.br + +.EE + +.IP "\fBint i2c_read_byte_data(int pi, unsigned handle, unsigned i2c_reg)\fP" +.IP "" 4 +This reads a single byte from the specified register of the device +associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + handle: >=0, as returned by a call to \fBi2c_open\fP. +.br +i2c_reg: 0-255, the register to read. +.br + +.EE + +.br + +.br +Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +.br + +.br +Read byte. SMBus 2.0 5.5.5 + +.EX +S Addr Wr [A] i2c_reg [A] S Addr Rd [A] [Data] NA P +.br + +.EE + +.IP "\fBint i2c_read_word_data(int pi, unsigned handle, unsigned i2c_reg)\fP" +.IP "" 4 +This reads a single 16 bit word from the specified register of the device +associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + handle: >=0, as returned by a call to \fBi2c_open\fP. +.br +i2c_reg: 0-255, the register to read. +.br + +.EE + +.br + +.br +Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +.br + +.br +Read word. SMBus 2.0 5.5.5 + +.EX +S Addr Wr [A] i2c_reg [A] +.br + S Addr Rd [A] [DataLow] A [DataHigh] NA P +.br + +.EE + +.IP "\fBint i2c_process_call(int pi, unsigned handle, unsigned i2c_reg, unsigned wVal)\fP" +.IP "" 4 +This writes 16 bits of data to the specified register of the device +associated with handle and and reads 16 bits of data in return. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + handle: >=0, as returned by a call to \fBi2c_open\fP. +.br +i2c_reg: 0-255, the register to write/read. +.br + wVal: 0-0xFFFF, the value to write. +.br + +.EE + +.br + +.br +Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +.br + +.br +Process call. SMBus 2.0 5.5.6 + +.EX +S Addr Wr [A] i2c_reg [A] wVal_Low [A] wVal_High [A] +.br + S Addr Rd [A] [DataLow] A [DataHigh] NA P +.br + +.EE + +.IP "\fBint i2c_write_block_data(int pi, unsigned handle, unsigned i2c_reg, char *buf, unsigned count)\fP" +.IP "" 4 +This writes up to 32 bytes to the specified register of the device +associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + handle: >=0, as returned by a call to \fBi2c_open\fP. +.br +i2c_reg: 0-255, the register to write. +.br + buf: an array with the data to send. +.br + count: 1-32, the number of bytes to write. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +.br + +.br +Block write. SMBus 2.0 5.5.7 + +.EX +S Addr Wr [A] i2c_reg [A] count [A] buf0 [A] buf1 [A] ... +.br + [A] bufn [A] P +.br + +.EE + +.IP "\fBint i2c_read_block_data(int pi, unsigned handle, unsigned i2c_reg, char *buf)\fP" +.IP "" 4 +This reads a block of up to 32 bytes from the specified register of +the device associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + handle: >=0, as returned by a call to \fBi2c_open\fP. +.br +i2c_reg: 0-255, the register to read. +.br + buf: an array to receive the read data. +.br + +.EE + +.br + +.br +The amount of returned data is set by the device. + +.br + +.br +Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +.br + +.br +Block read. SMBus 2.0 5.5.7 + +.EX +S Addr Wr [A] i2c_reg [A] +.br + S Addr Rd [A] [Count] A [buf0] A [buf1] A ... A [bufn] NA P +.br + +.EE + +.IP "\fBint i2c_block_process_call(int pi, unsigned handle, unsigned i2c_reg, char *buf, unsigned count)\fP" +.IP "" 4 +This writes data bytes to the specified register of the device +associated with handle and reads a device specified number +of bytes of data in return. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + handle: >=0, as returned by a call to \fBi2c_open\fP. +.br +i2c_reg: 0-255, the register to write/read. +.br + buf: an array with the data to send and to receive the read data. +.br + count: 1-32, the number of bytes to write. +.br + +.EE + +.br + +.br + +.br + +.br +Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +.br + +.br +The smbus 2.0 documentation states that a minimum of 1 byte may be +sent and a minimum of 1 byte may be received. The total number of +bytes sent/received must be 32 or less. + +.br + +.br +Block write-block read. SMBus 2.0 5.5.8 + +.EX +S Addr Wr [A] i2c_reg [A] count [A] buf0 [A] ... +.br + S Addr Rd [A] [Count] A [Data] ... A P +.br + +.EE + +.IP "\fBint i2c_read_i2c_block_data(int pi, unsigned handle, unsigned i2c_reg, char *buf, unsigned count)\fP" +.IP "" 4 +This reads count bytes from the specified register of the device +associated with handle . The count may be 1-32. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + handle: >=0, as returned by a call to \fBi2c_open\fP. +.br +i2c_reg: 0-255, the register to read. +.br + buf: an array to receive the read data. +.br + count: 1-32, the number of bytes to read. +.br + +.EE + +.br + +.br +Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +.br + +.br + +.EX +S Addr Wr [A] i2c_reg [A] +.br + S Addr Rd [A] [buf0] A [buf1] A ... A [bufn] NA P +.br + +.EE + +.IP "\fBint i2c_write_i2c_block_data(int pi, unsigned handle, unsigned i2c_reg, char *buf, unsigned count)\fP" +.IP "" 4 +This writes 1 to 32 bytes to the specified register of the device +associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + handle: >=0, as returned by a call to \fBi2c_open\fP. +.br +i2c_reg: 0-255, the register to write. +.br + buf: the data to write. +.br + count: 1-32, the number of bytes to write. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +.br + +.br + +.EX +S Addr Wr [A] i2c_reg [A] buf0 [A] buf1 [A] ... [A] bufn [A] P +.br + +.EE + +.IP "\fBint i2c_read_device(int pi, unsigned handle, char *buf, unsigned count)\fP" +.IP "" 4 +This reads count bytes from the raw device into buf. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBi2c_open\fP. +.br + buf: an array to receive the read data bytes. +.br + count: >0, the number of bytes to read. +.br + +.EE + +.br + +.br +Returns count (>0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_READ_FAILED. + +.br + +.br + +.EX +S Addr Rd [A] [buf0] A [buf1] A ... A [bufn] NA P +.br + +.EE + +.IP "\fBint i2c_write_device(int pi, unsigned handle, char *buf, unsigned count)\fP" +.IP "" 4 +This writes count bytes from buf to the raw device. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBi2c_open\fP. +.br + buf: an array containing the data bytes to write. +.br + count: >0, the number of bytes to write. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +.br + +.br + +.EX +S Addr Wr [A] buf0 [A] buf1 [A] ... [A] bufn [A] P +.br + +.EE + +.IP "\fBint i2c_zip(int pi, unsigned handle, char *inBuf, unsigned inLen, char *outBuf, unsigned outLen)\fP" +.IP "" 4 +This function executes a sequence of I2C operations. The +operations to be performed are specified by the contents of inBuf +which contains the concatenated command codes and associated data. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBi2cOpen\fP +.br + inBuf: pointer to the concatenated I2C commands, see below +.br + inLen: size of command buffer +.br +outBuf: pointer to buffer to hold returned data +.br +outLen: size of output buffer +.br + +.EE + +.br + +.br +Returns >= 0 if OK (the number of bytes read), otherwise +PI_BAD_HANDLE, PI_BAD_POINTER, PI_BAD_I2C_CMD, PI_BAD_I2C_RLEN. +PI_BAD_I2C_WLEN, or PI_BAD_I2C_SEG. + +.br + +.br +The following command codes are supported: + +.br + +.br +Name Cmd & Data Meaning + +.br +End 0 No more commands + +.br +Escape 1 Next P is two bytes + +.br +On 2 Switch combined flag on + +.br +Off 3 Switch combined flag off + +.br +Address 4 P Set I2C address to P + +.br +Flags 5 lsb msb Set I2C flags to lsb + (msb << 8) + +.br +Read 6 P Read P bytes of data + +.br +Write 7 P ... Write P bytes of data + +.br + +.br + +.br +The address, read, and write commands take a parameter P. +Normally P is one byte (0-255). If the command is preceded by +the Escape command then P is two bytes (0-65535, least significant +byte first). + +.br + +.br +The address defaults to that associated with the handle. +The flags default to 0. The address and flags maintain their +previous value until updated. + +.br + +.br +The returned I2C data is stored in consecutive locations of outBuf. + +.br + +.br +\fBExample\fP +.br + +.EX +Set address 0x53, write 0x32, read 6 bytes +.br +Set address 0x1E, write 0x03, read 6 bytes +.br +Set address 0x68, write 0x1B, read 8 bytes +.br +End +.br + +.br +0x04 0x53 0x07 0x01 0x32 0x06 0x06 +.br +0x04 0x1E 0x07 0x01 0x03 0x06 0x06 +.br +0x04 0x68 0x07 0x01 0x1B 0x06 0x08 +.br +0x00 +.br + +.EE + +.br + +.br + +.IP "\fBint bb_i2c_open(int pi, unsigned SDA, unsigned SCL, unsigned baud)\fP" +.IP "" 4 +This function selects a pair of gpios for bit banging I2C at a +specified baud rate. + +.br + +.br +Bit banging I2C allows for certain operations which are not possible +with the standard I2C driver. + +.br + +.br +o baud rates as low as 50 +.br +o repeated starts +.br +o clock stretching +.br +o I2C on any pair of spare gpios + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + SDA: 0-31 +.br + SCL: 0-31 +.br +baud: 50-500000 +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_I2C_BAUD, or +PI_GPIO_IN_USE. + +.br + +.br +NOTE: + +.br + +.br +The gpios used for SDA and SCL must have pull-ups to 3V3 connected. As +a guide the hardware pull-ups on pins 3 and 5 are 1k8 in value. + +.IP "\fBint bb_i2c_close(int pi, unsigned SDA)\fP" +.IP "" 4 +This function stops bit banging I2C on a pair of gpios previously +opened with \fBbb_i2c_open\fP. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +SDA: 0-31, the SDA gpio used in a prior call to \fBbb_i2c_open\fP +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_I2C_GPIO. + +.IP "\fBint bb_i2c_zip(int pi, unsigned SDA, char *inBuf, unsigned inLen, char *outBuf, unsigned outLen)\fP" +.IP "" 4 +This function executes a sequence of bit banged I2C operations. The +operations to be performed are specified by the contents of inBuf +which contains the concatenated command codes and associated data. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + SDA: 0-31 (as used in a prior call to \fBbb_i2c_open\fP) +.br + inBuf: pointer to the concatenated I2C commands, see below +.br + inLen: size of command buffer +.br +outBuf: pointer to buffer to hold returned data +.br +outLen: size of output buffer +.br + +.EE + +.br + +.br +Returns >= 0 if OK (the number of bytes read), otherwise +PI_BAD_USER_GPIO, PI_NOT_I2C_GPIO, PI_BAD_POINTER, +PI_BAD_I2C_CMD, PI_BAD_I2C_RLEN, PI_BAD_I2C_WLEN, +PI_I2C_READ_FAILED, or PI_I2C_WRITE_FAILED. + +.br + +.br +The following command codes are supported: + +.br + +.br +Name Cmd & Data Meaning + +.br +End 0 No more commands + +.br +Escape 1 Next P is two bytes + +.br +Start 2 Start condition + +.br +Stop 3 Stop condition + +.br +Address 4 P Set I2C address to P + +.br +Flags 5 lsb msb Set I2C flags to lsb + (msb << 8) + +.br +Read 6 P Read P bytes of data + +.br +Write 7 P ... Write P bytes of data + +.br + +.br + +.br +The address, read, and write commands take a parameter P. +Normally P is one byte (0-255). If the command is preceded by +the Escape command then P is two bytes (0-65535, least significant +byte first). + +.br + +.br +The address and flags default to 0. The address and flags maintain +their previous value until updated. + +.br + +.br +No flags are currently defined. + +.br + +.br +The returned I2C data is stored in consecutive locations of outBuf. + +.br + +.br +\fBExample\fP +.br + +.EX +Set address 0x53 +.br +start, write 0x32, (re)start, read 6 bytes, stop +.br +Set address 0x1E +.br +start, write 0x03, (re)start, read 6 bytes, stop +.br +Set address 0x68 +.br +start, write 0x1B, (re)start, read 8 bytes, stop +.br +End +.br + +.br +0x04 0x53 +.br +0x02 0x07 0x01 0x32 0x02 0x06 0x06 0x03 +.br + +.br +0x04 0x1E +.br +0x02 0x07 0x01 0x03 0x02 0x06 0x06 0x03 +.br + +.br +0x04 0x68 +.br +0x02 0x07 0x01 0x1B 0x02 0x06 0x08 0x03 +.br + +.br +0x00 +.br + +.EE + +.IP "\fBint spi_open(int pi, unsigned spi_channel, unsigned baud, unsigned spi_flags)\fP" +.IP "" 4 +This function returns a handle for the SPI device on channel. +Data will be transferred at baud bits per second. The flags may +be used to modify the default behaviour of 4-wire operation, mode 0, +active low chip select. + +.br + +.br +An auxiliary SPI device is available on the A+/B+/Pi2 and may be +selected by setting the A bit in the flags. The auxiliary +device has 3 chip selects and a selectable word size in bits. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +spi_channel: 0-1 (0-2 for A+/B+/Pi2 auxiliary device). +.br + baud: 32K-125M (values above 30M are unlikely to work). +.br + spi_flags: see below. +.br + +.EE + +.br + +.br +Returns a handle (>=0) if OK, otherwise PI_BAD_SPI_CHANNEL, +PI_BAD_SPI_SPEED, PI_BAD_FLAGS, PI_NO_AUX_SPI, or PI_SPI_OPEN_FAILED. + +.br + +.br +spi_flags consists of the least significant 22 bits. + +.br + +.br + +.EX +21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +.br + b b b b b b R T n n n n W A u2 u1 u0 p2 p1 p0 m m +.br + +.EE + +.br + +.br +mm defines the SPI mode. + +.br + +.br +Warning: modes 1 and 3 do not appear to work on the auxiliary device. + +.br + +.br + +.EX +Mode POL PHA +.br + 0 0 0 +.br + 1 0 1 +.br + 2 1 0 +.br + 3 1 1 +.br + +.EE + +.br + +.br +px is 0 if CEx is active low (default) and 1 for active high. + +.br + +.br +ux is 0 if the CEx gpio is reserved for SPI (default) and 1 otherwise. + +.br + +.br +A is 0 for the standard SPI device, 1 for the auxiliary SPI. The +auxiliary device is only present on the A+/B+/Pi2. + +.br + +.br +W is 0 if the device is not 3-wire, 1 if the device is 3-wire. Standard +SPI device only. + +.br + +.br +nnnn defines the number of bytes (0-15) to write before switching +the MOSI line to MISO to read data. This field is ignored +if W is not set. Standard SPI device only. + +.br + +.br +T is 1 if the least significant bit is transmitted on MOSI first, the +default (0) shifts the most significant bit out first. Auxiliary SPI +device only. + +.br + +.br +R is 1 if the least significant bit is received on MISO first, the +default (0) receives the most significant bit first. Auxiliary SPI +device only. + +.br + +.br +bbbbbb defines the word size in bits (0-32). The default (0) +sets 8 bits per word. Auxiliary SPI device only. + +.br + +.br +The other bits in flags should be set to zero. + +.IP "\fBint spi_close(int pi, unsigned handle)\fP" +.IP "" 4 +This functions closes the SPI device identified by the handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBspi_open\fP. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE. + +.IP "\fBint spi_read(int pi, unsigned handle, char *buf, unsigned count)\fP" +.IP "" 4 +This function reads count bytes of data from the SPI +device associated with the handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBspi_open\fP. +.br + buf: an array to receive the read data bytes. +.br + count: the number of bytes to read. +.br + +.EE + +.br + +.br +Returns the number of bytes transferred if OK, otherwise +PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED. + +.IP "\fBint spi_write(int pi, unsigned handle, char *buf, unsigned count)\fP" +.IP "" 4 +This function writes count bytes of data from buf to the SPI +device associated with the handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBspi_open\fP. +.br + buf: the data bytes to write. +.br + count: the number of bytes to write. +.br + +.EE + +.br + +.br +Returns the number of bytes transferred if OK, otherwise +PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED. + +.IP "\fBint spi_xfer(int pi, unsigned handle, char *txBuf, char *rxBuf, unsigned count)\fP" +.IP "" 4 +This function transfers count bytes of data from txBuf to the SPI +device associated with the handle. Simultaneously count bytes of +data are read from the device and placed in rxBuf. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBspi_open\fP. +.br + txBuf: the data bytes to write. +.br + rxBuf: the received data bytes. +.br + count: the number of bytes to transfer. +.br + +.EE + +.br + +.br +Returns the number of bytes transferred if OK, otherwise +PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED. + +.IP "\fBint serial_open(int pi, char *ser_tty, unsigned baud, unsigned ser_flags)\fP" +.IP "" 4 +This function opens a serial device at a specified baud rate +with specified flags. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + ser_tty: the serial device to open, /dev/tty*. +.br + baud: the baud rate in bits per second, see below. +.br +ser_flags: 0. +.br + +.EE + +.br + +.br +Returns a handle (>=0) if OK, otherwise PI_NO_HANDLE, or +PI_SER_OPEN_FAILED. + +.br + +.br +The baud rate must be one of 50, 75, 110, 134, 150, +200, 300, 600, 1200, 1800, 2400, 4800, 9500, 19200, +38400, 57600, 115200, or 230400. + +.br + +.br +No flags are currently defined. This parameter should be set to zero. + +.IP "\fBint serial_close(int pi, unsigned handle)\fP" +.IP "" 4 +This function closes the serial device associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBserial_open\fP. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE. + +.IP "\fBint serial_write_byte(int pi, unsigned handle, unsigned bVal)\fP" +.IP "" 4 +This function writes bVal to the serial port associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBserial_open\fP. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_SER_WRITE_FAILED. + +.IP "\fBint serial_read_byte(int pi, unsigned handle)\fP" +.IP "" 4 +This function reads a byte from the serial port associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBserial_open\fP. +.br + +.EE + +.br + +.br +Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED. + +.IP "\fBint serial_write(int pi, unsigned handle, char *buf, unsigned count)\fP" +.IP "" 4 +This function writes count bytes from buf to the the serial port +associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBserial_open\fP. +.br + buf: the array of bytes to write. +.br + count: the number of bytes to write. +.br + +.EE + +.br + +.br +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_SER_WRITE_FAILED. + +.IP "\fBint serial_read(int pi, unsigned handle, char *buf, unsigned count)\fP" +.IP "" 4 +This function reads up to count bytes from the the serial port +associated with handle and writes them to buf. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBserial_open\fP. +.br + buf: an array to receive the read data. +.br + count: the maximum number of bytes to read. +.br + +.EE + +.br + +.br +Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED. + +.IP "\fBint serial_data_available(int pi, unsigned handle)\fP" +.IP "" 4 +Returns the number of bytes available to be read from the +device associated with handle. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +handle: >=0, as returned by a call to \fBserial_open\fP. +.br + +.EE + +.br + +.br +Returns the number of bytes of data available (>=0) if OK, +otherwise PI_BAD_HANDLE. + +.IP "\fBint custom_1(int pi, unsigned arg1, unsigned arg2, char *argx, unsigned argc)\fP" +.IP "" 4 +This function is available for user customisation. + +.br + +.br +It returns a single integer value. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +arg1: >=0 +.br +arg2: >=0 +.br +argx: extra (byte) arguments +.br +argc: number of extra arguments +.br + +.EE + +.br + +.br +Returns >= 0 if OK, less than 0 indicates a user defined error. + +.IP "\fBint custom_2(int pi, unsigned arg1, char *argx, unsigned argc, char *retBuf, unsigned retMax)\fP" +.IP "" 4 +This function is available for user customisation. + +.br + +.br +It differs from custom_1 in that it returns an array of bytes +rather than just an integer. + +.br + +.br +The return value is an integer indicating the number of returned bytes. + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br + arg1: >=0 +.br + argc: extra (byte) arguments +.br + count: number of extra arguments +.br +retBuf: buffer for returned data +.br +retMax: maximum number of bytes to return +.br + +.EE + +.br + +.br +Returns >= 0 if OK, less than 0 indicates a user defined error. + +.br + +.br +Note, the number of returned bytes will be retMax or less. + +.IP "\fBint callback(int pi, unsigned user_gpio, unsigned edge, CBFunc_t f)\fP" +.IP "" 4 +This function initialises a new callback. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE. +.br + f: the callback function. +.br + +.EE + +.br + +.br +The function returns a callback id if OK, otherwise pigif_bad_malloc, +pigif_duplicate_callback, or pigif_bad_callback. + +.br + +.br +The callback is called with the gpio, edge, and tick, whenever the +gpio has the identified edge. + +.IP "\fBint callback_ex(int pi, unsigned user_gpio, unsigned edge, CBFuncEx_t f, void *userdata)\fP" +.IP "" 4 +This function initialises a new callback. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE. +.br + f: the callback function. +.br + userdata: a pointer to arbitrary user data. +.br + +.EE + +.br + +.br +The function returns a callback id if OK, otherwise pigif_bad_malloc, +pigif_duplicate_callback, or pigif_bad_callback. + +.br + +.br +The callback is called with the gpio, edge, tick, and user, whenever +the gpio has the identified edge. + +.IP "\fBint callback_cancel(unsigned callback_id)\fP" +.IP "" 4 +This function cancels a callback identified by its id. + +.br + +.br + +.EX +callback_id: >=0, as returned by a call to \fBcallback\fP or \fBcallback_ex\fP. +.br + +.EE + +.br + +.br +The function returns 0 if OK, otherwise pigif_callback_not_found. + +.IP "\fBint wait_for_edge(int pi, unsigned user_gpio, unsigned edge, double timeout)\fP" +.IP "" 4 +This function waits for edge on the gpio for up to timeout +seconds. + +.br + +.br + +.EX + pi: 0- (as returned by \fBpigpio_start\fP). +.br +user_gpio: 0-31. +.br + edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE. +.br + timeout: >=0. +.br + +.EE + +.br + +.br +The function returns 1 if the edge occurred, otherwise 0. + +.br + +.br +The function returns when the edge occurs or after the timeout. +.SH PARAMETERS + +.br + +.br + +.IP "\fBactive\fP: 0-1000000" 0 + +.br + +.br +The number of microseconds level changes are reported for once +a noise filter has been triggered (by \fBsteady\fP microseconds of +a stable level). + +.br + +.br + +.IP "\fB*addrStr\fP" 0 +A string specifying the host or IP address of the Pi running +the pigpio daemon. It may be NULL in which case localhost +is used unless overridden by the PIGPIO_ADDR environment +variable. + +.br + +.br + +.IP "\fBarg1\fP" 0 +An unsigned argument passed to a user customised function. Its +meaning is defined by the customiser. + +.br + +.br + +.IP "\fBarg2\fP" 0 +An unsigned argument passed to a user customised function. Its +meaning is defined by the customiser. + +.br + +.br + +.IP "\fBargc\fP" 0 +The count of bytes passed to a user customised function. + +.br + +.br + +.IP "\fB*argx\fP" 0 +A pointer to an array of bytes passed to a user customised function. +Its meaning and content is defined by the customiser. + +.br + +.br + +.IP "\fBbaud\fP" 0 +The speed of serial communication (I2C, SPI, serial link, waves) in +bits per second. + +.br + +.br + +.IP "\fBbit\fP" 0 +A value of 0 or 1. + +.br + +.br + +.IP "\fBbits\fP" 0 +A value used to select gpios. If bit n of bits is set then gpio n is +selected. + +.br + +.br +A convenient way to set bit n is to or in (1<=0, as returned by a call to \fBcallback\fP or \fBcallback_ex\fP. This is +passed to \fBcallback_cancel\fP to cancel the callback. + +.br + +.br + +.IP "\fBCBFunc_t\fP" 0 + +.EX +typedef void (*CBFunc_t) +.br + (unsigned user_gpio, unsigned level, uint32_t tick); +.br + +.EE + +.br + +.br + +.IP "\fBCBFuncEx_t\fP" 0 + +.EX +typedef void (*CBFuncEx_t) +.br + (unsigned user_gpio, unsigned level, uint32_t tick, void * user); +.br + +.EE + +.br + +.br + +.IP "\fBchar\fP" 0 +A single character, an 8 bit quantity able to store 0-255. + +.br + +.br + +.IP "\fBclkfreq\fP: 4689-250000000 (250M)" 0 +The hardware clock frequency. + +.br + +.br + +.IP "\fBcount\fP" 0 +The number of bytes to be transferred in an I2C, SPI, or Serial +command. + +.br + +.br + +.IP "\fBdata_bits\fP: 1-32" 0 +The number of data bits in each character of serial data. + +.br + +.br + +.EX +#define PI_MIN_WAVE_DATABITS 1 +.br +#define PI_MAX_WAVE_DATABITS 32 +.br + +.EE + +.br + +.br + +.IP "\fBdouble\fP" 0 +A floating point number. + +.br + +.br + +.IP "\fBdutycycle\fP: 0-range" 0 +A number representing the ratio of on time to off time for PWM. + +.br + +.br +The number may vary between 0 and range (default 255) where +0 is off and range is fully on. + +.br + +.br + +.IP "\fBedge\fP" 0 +Used to identify a gpio level transition of interest. A rising edge is +a level change from 0 to 1. A falling edge is a level change from 1 to 0. + +.br + +.br + +.EX +RISING_EDGE 0 +.br +FALLING_EDGE 1 +.br +EITHER_EDGE. 2 +.br + +.EE + +.br + +.br + +.IP "\fBerrnum\fP" 0 +A negative number indicating a function call failed and the nature +of the error. + +.br + +.br + +.IP "\fBf\fP" 0 +A function. + +.br + +.br + +.IP "\fBfrequency\fP: 0-" 0 +The number of times a gpio is swiched on and off per second. This +can be set per gpio and may be as little as 5Hz or as much as +40KHz. The gpio will be on for a proportion of the time as defined +by its dutycycle. + +.br + +.br + +.br + +.br + +.IP "\fBgpio\fP" 0 +A Broadcom numbered gpio, in the range 0-53. + +.br + +.br +There are 54 General Purpose Input Outputs (gpios) named gpio0 through +gpio53. + +.br + +.br +They are split into two banks. Bank 1 consists of gpio0 through +gpio31. Bank 2 consists of gpio32 through gpio53. + +.br + +.br +All the gpios which are safe for the user to read and write are in +bank 1. Not all gpios in bank 1 are safe though. Type 1 boards +have 17 safe gpios. Type 2 boards have 21. Type 3 boards have 26. + +.br + +.br +See \fBget_hardware_revision\fP. + +.br + +.br +The user gpios are marked with an X in the following table. + +.br + +.br + +.EX + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +.br +Type 1 X X - - X - - X X X X X - - X X +.br +Type 2 - - X X X - - X X X X X - - X X +.br +Type 3 X X X X X X X X X X X X X X +.br + +.br + 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 +.br +Type 1 - X X - - X X X X X - - - - - - +.br +Type 2 - X X - - - X X X X - X X X X X +.br +Type 3 X X X X X X X X X X X X - - - - +.br + +.EE + +.br + +.br + +.IP "\fBgpioPulse_t\fP" 0 + +.EX +typedef struct +.br +{ +.br +uint32_t gpioOn; +.br +uint32_t gpioOff; +.br +uint32_t usDelay; +.br +} gpioPulse_t; +.br + +.EE + +.br + +.br + +.IP "\fBgpioThreadFunc_t\fP" 0 + +.EX +typedef void *(gpioThreadFunc_t) (void *); +.br + +.EE + +.br + +.br + +.IP "\fBhandle\fP: 0-" 0 +A number referencing an object opened by one of \fBi2c_open\fP, \fBnotify_open\fP, +\fBserial_open\fP, and \fBspi_open\fP. + +.br + +.br + +.IP "\fBi2c_addr\fP" 0 +The address of a device on the I2C bus. + +.br + +.br + +.IP "\fBi2c_bus\fP: 0-1" 0 +An I2C bus, 0 or 1. + +.br + +.br + +.IP "\fBi2c_flags\fP: 0" 0 +Flags which modify an I2C open command. None are currently defined. + +.br + +.br + +.IP "\fBi2c_reg\fP: 0-255" 0 +A register of an I2C device. + +.br + +.br + +.IP "\fB*inBuf\fP" 0 +A buffer used to pass data to a function. + +.br + +.br + +.IP "\fBinLen\fP" 0 +The number of bytes of data in a buffer. + +.br + +.br + +.IP "\fBint\fP" 0 +A whole number, negative or positive. + +.br + +.br + +.IP "\fBinvert\fP" 0 +A flag used to set normal or inverted bit bang serial data level logic. + +.br + +.br + +.IP "\fBlevel\fP" 0 +The level of a gpio. Low or High. + +.br + +.br + +.EX +PI_OFF 0 +.br +PI_ON 1 +.br + +.br +PI_CLEAR 0 +.br +PI_SET 1 +.br + +.br +PI_LOW 0 +.br +PI_HIGH 1 +.br + +.EE + +.br + +.br +There is one exception. If a watchdog expires on a gpio the level will be +reported as PI_TIMEOUT. See \fBset_watchdog\fP. + +.br + +.br + +.EX +PI_TIMEOUT 2 +.br + +.EE + +.br + +.br + +.IP "\fBmode\fP: 0-7" 0 +The operational mode of a gpio, normally INPUT or OUTPUT. + +.br + +.br + +.EX +PI_INPUT 0 +.br +PI_OUTPUT 1 +.br +PI_ALT0 4 +.br +PI_ALT1 5 +.br +PI_ALT2 6 +.br +PI_ALT3 7 +.br +PI_ALT4 3 +.br +PI_ALT5 2 +.br + +.EE + +.br + +.br + +.IP "\fBnumBytes\fP" 0 +The number of bytes used to store characters in a string. Depending +on the number of bits per character there may be 1, 2, or 4 bytes +per character. + +.br + +.br + +.IP "\fBnumPar\fP: 0-10" 0 +The number of parameters passed to a script. + +.br + +.br + +.IP "\fBnumPulses\fP" 0 +The number of pulses to be added to a waveform. + +.br + +.br + +.IP "\fBoffset\fP" 0 +The associated data starts this number of microseconds from the start of +the waveform. + +.br + +.br + +.IP "\fB*outBuf\fP" 0 +A buffer used to return data from a function. + +.br + +.br + +.IP "\fBoutLen\fP" 0 +The size in bytes of an output buffer. + +.br + +.br + +.IP "\fB*param\fP" 0 +An array of script parameters. + +.br + +.br + +.IP "\fBpi\fP" 0 +An integer defining a connected Pi. The value is returned by +\fBpigpio_start\fP upon success. + +.br + +.br + +.IP "\fB*portStr\fP" 0 +A string specifying the port address used by the Pi running +the pigpio daemon. It may be NULL in which case "8888" +is used unless overridden by the PIGPIO_PORT environment +variable. + +.br + +.br + +.IP "\fB*pth\fP" 0 +A thread identifier, returned by \fBstart_thread\fP. + +.br + +.br + +.br + +.br + +.IP "\fBpthread_t\fP" 0 +A thread identifier. + +.br + +.br + +.IP "\fBpud\fP: 0-2" 0 +The setting of the pull up/down resistor for a gpio, which may be off, +pull-up, or pull-down. + +.EX +PI_PUD_OFF 0 +.br +PI_PUD_DOWN 1 +.br +PI_PUD_UP 2 +.br + +.EE + +.br + +.br + +.IP "\fBpulseLen\fP" 0 +1-100, the length of a trigger pulse in microseconds. + +.br + +.br + +.IP "\fB*pulses\fP" 0 +An array of pulses to be added to a waveform. + +.br + +.br + +.IP "\fBpulsewidth\fP: 0, 500-2500" 0 + +.EX +PI_SERVO_OFF 0 +.br +PI_MIN_SERVO_PULSEWIDTH 500 +.br +PI_MAX_SERVO_PULSEWIDTH 2500 +.br + +.EE + +.br + +.br + +.IP "\fBPWMduty\fP: 0-1000000 (1M)" 0 +The hardware PWM dutycycle. + +.br + +.br + +.EX +#define PI_HW_PWM_RANGE 1000000 +.br + +.EE + +.br + +.br + +.IP "\fBPWMfreq\fP: 1-125000000 (125M)" 0 +The hardware PWM frequency. + +.br + +.br + +.EX +#define PI_HW_PWM_MIN_FREQ 1 +.br +#define PI_HW_PWM_MAX_FREQ 125000000 +.br + +.EE + +.br + +.br + +.IP "\fBrange\fP: 25-40000" 0 +The permissible dutycycle values are 0-range. + +.EX +PI_MIN_DUTYCYCLE_RANGE 25 +.br +PI_MAX_DUTYCYCLE_RANGE 40000 +.br + +.EE + +.br + +.br + +.IP "\fB*retBuf\fP" 0 +A buffer to hold a number of bytes returned to a used customised function, + +.br + +.br + +.IP "\fBretMax\fP" 0 +The maximum number of bytes a user customised function should return. + +.br + +.br + +.br + +.br + +.IP "\fB*rxBuf\fP" 0 +A pointer to a buffer to receive data. + +.br + +.br + +.IP "\fBSCL\fP" 0 +The user gpio to use for the clock when bit banging I2C. + +.br + +.br + +.IP "\fB*script\fP" 0 +A pointer to the text of a script. + +.br + +.br + +.IP "\fBscript_id\fP" 0 +An id of a stored script as returned by \fBstore_script\fP. + +.br + +.br + +.IP "\fBSDA\fP" 0 +The user gpio to use for data when bit banging I2C. + +.br + +.br + +.IP "\fBseconds\fP" 0 +The number of seconds. + +.br + +.br + +.IP "\fBser_flags\fP" 0 +Flags which modify a serial open command. None are currently defined. + +.br + +.br + +.IP "\fB*ser_tty\fP" 0 +The name of a serial tty device, e.g. /dev/ttyAMA0, /dev/ttyUSB0, /dev/tty1. + +.br + +.br + +.IP "\fBsize_t\fP" 0 +A standard type used to indicate the size of an object in bytes. + +.br + +.br + +.IP "\fBspi_channel\fP" 0 +A SPI channel, 0-2. + +.br + +.br + +.IP "\fBspi_flags\fP" 0 +See \fBspi_open\fP. + +.br + +.br + +.IP "\fBsteady\fP: 0-300000" 0 + +.br + +.br +The number of microseconds level changes must be stable for +before reporting the level changed (\fBset_glitch_filter\fP) or triggering +the active part of a noise filter (\fBset_noise_filter\fP). + +.br + +.br + +.IP "\fBstop_bits\fP: 2-8" 0 +The number of (half) stop bits to be used when adding serial data +to a waveform. + +.br + +.br + +.EX +#define PI_MIN_WAVE_HALFSTOPBITS 2 +.br +#define PI_MAX_WAVE_HALFSTOPBITS 8 +.br + +.EE + +.br + +.br + +.IP "\fB*str\fP" 0 + An array of characters. + +.br + +.br + +.IP "\fBthread_func\fP" 0 +A function of type gpioThreadFunc_t used as the main function of a +thread. + +.br + +.br + +.IP "\fBtimeout\fP" 0 +A gpio watchdog timeout in milliseconds. + +.EX +PI_MIN_WDOG_TIMEOUT 0 +.br +PI_MAX_WDOG_TIMEOUT 60000 +.br + +.EE + +.br + +.br + +.IP "\fB*txBuf\fP" 0 +An array of bytes to transmit. + +.br + +.br + +.IP "\fBuint32_t\fP: 0-0-4,294,967,295 (Hex 0x0-0xFFFFFFFF)" 0 +A 32-bit unsigned value. + +.br + +.br + +.IP "\fBunsigned\fP" 0 +A whole number >= 0. + +.br + +.br + +.IP "\fBuser_gpio\fP" 0 +0-31, a Broadcom numbered gpio. + +.br + +.br +See \fBgpio\fP. + +.br + +.br + +.IP "\fB*userdata\fP" 0 + +.br + +.br +A pointer to arbitrary user data. This may be used to identify the instance. + +.br + +.br +You must ensure that the pointer is in scope at the time it is processed. If +it is a pointer to a global this is automatic. Do not pass the address of a +local variable. If you want to pass a transient object then use the +following technique. + +.br + +.br +In the calling function: + +.br + +.br +user_type *userdata; +.br +user_type my_userdata; + +.br + +.br +userdata = malloc(sizeof(user_type)); +.br +*userdata = my_userdata; + +.br + +.br +In the receiving function: + +.br + +.br +user_type my_userdata = *(user_type*)userdata; + +.br + +.br +free(userdata); + +.br + +.br + +.IP "\fBvoid\fP" 0 +Denoting no parameter is required + +.br + +.br + +.IP "\fBwave_add_*\fP" 0 +One of \fBwave_add_new\fP, \fBwave_add_generic\fP, \fBwave_add_serial\fP. + +.br + +.br + +.IP "\fBwave_id\fP" 0 +A number representing a waveform created by \fBwave_create\fP. + +.br + +.br + +.IP "\fBwave_send_*\fP" 0 +One of \fBwave_send_once\fP, \fBwave_send_repeat\fP. + +.br + +.br + +.IP "\fBwVal\fP: 0-65535 (Hex 0x0-0xFFFF, Octal 0-0177777)" 0 +A 16-bit word value. + +.br + +.br +.SH pigpiod_if2 Error Codes + +.EX + +.br +typedef enum +.br +{ +.br + pigif_bad_send = -2000, +.br + pigif_bad_recv = -2001, +.br + pigif_bad_getaddrinfo = -2002, +.br + pigif_bad_connect = -2003, +.br + pigif_bad_socket = -2004, +.br + pigif_bad_noib = -2005, +.br + pigif_duplicate_callback = -2006, +.br + pigif_bad_malloc = -2007, +.br + pigif_bad_callback = -2008, +.br + pigif_notify_failed = -2009, +.br + pigif_callback_not_found = -2010, +.br + pigif_unconnected_pi = -2011, +.br + pigif_too_many_pis = -2012, +.br +} pigifError_t; +.br + +.br + +.EE + +.SH SEE ALSO + +pigpiod(1), pig2vcd(1), pigs(1), pigpio(3), pigpiod_if(3) +.SH AUTHOR + +joan@abyz.co.uk diff --git a/pigpiod_if2.c b/pigpiod_if2.c new file mode 100644 index 0000000..110063d --- /dev/null +++ b/pigpiod_if2.c @@ -0,0 +1,1659 @@ +/* +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 +*/ + +/* PIGPIOD_IF2_VERSION 1 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "pigpio.h" +#include "command.h" + +#include "pigpiod_if2.h" + +#define PI_MAX_REPORTS_PER_READ 4096 + +#define STACK_SIZE (256*1024) + +#define MAX_PI 32 + +typedef void (*CBF_t) (); + +struct callback_s +{ + + int id; + int pi; + int gpio; + int edge; + CBF_t f; + void * user; + int ex; + callback_t *prev; + callback_t *next; +}; + +/* GLOBALS ---------------------------------------------------------------- */ + +static int gPiInUse [MAX_PI]; + +static int gPigCommand [MAX_PI]; +static int gPigHandle [MAX_PI]; +static int gPigNotify [MAX_PI]; + +static uint32_t gNotifyBits [MAX_PI]; +static uint32_t gLastLevel [MAX_PI]; + +static pthread_t *gPthNotify [MAX_PI]; + +static pthread_mutex_t gCmdMutex [MAX_PI]; +static int gCancelState [MAX_PI]; + +static callback_t *gCallBackFirst = 0; +static callback_t *gCallBackLast = 0; + +/* PRIVATE ---------------------------------------------------------------- */ + +static void _pml(int pi) +{ + int cancelState; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState); + pthread_mutex_lock(&gCmdMutex[pi]); + gCancelState[pi] = cancelState; +} + +static void _pmu(int pi) +{ + int cancelState; + + cancelState = gCancelState[pi]; + pthread_mutex_unlock(&gCmdMutex[pi]); + pthread_setcancelstate(cancelState, NULL); +} + +static int pigpio_command(int pi, int command, int p1, int p2, int rl) +{ + cmdCmd_t cmd; + + if ((pi < 0) || (pi >= MAX_PI) || !gPiInUse[pi]) + return pigif_unconnected_pi; + + cmd.cmd = command; + cmd.p1 = p1; + cmd.p2 = p2; + cmd.res = 0; + + _pml(pi); + + if (send(gPigCommand[pi], &cmd, sizeof(cmd), 0) != sizeof(cmd)) + { + _pmu(pi); + return pigif_bad_send; + } + + if (recv(gPigCommand[pi], &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd)) + { + _pmu(pi); + return pigif_bad_recv; + } + + if (rl) _pmu(pi); + + return cmd.res; +} + +static int pigpio_notify(int pi) +{ + cmdCmd_t cmd; + + if ((pi < 0) || (pi >= MAX_PI) || !gPiInUse[pi]) + return pigif_unconnected_pi; + + cmd.cmd = PI_CMD_NOIB; + cmd.p1 = 0; + cmd.p2 = 0; + cmd.res = 0; + + _pml(pi); + + if (send(gPigNotify[pi], &cmd, sizeof(cmd), 0) != sizeof(cmd)) + { + _pmu(pi); + return pigif_bad_send; + } + + if (recv(gPigNotify[pi], &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd)) + { + _pmu(pi); + return pigif_bad_recv; + } + + _pmu(pi); + + return cmd.res; +} + +static int pigpio_command_ext + (int pi, int command, int p1, int p2, int p3, + int extents, gpioExtent_t *ext, int rl) +{ + int i; + cmdCmd_t cmd; + + if ((pi < 0) || (pi >= MAX_PI) || !gPiInUse[pi]) + return pigif_unconnected_pi; + + cmd.cmd = command; + cmd.p1 = p1; + cmd.p2 = p2; + cmd.p3 = p3; + + _pml(pi); + + if (send(gPigCommand[pi], &cmd, sizeof(cmd), 0) != sizeof(cmd)) + { + _pmu(pi); + return pigif_bad_send; + } + + for (i=0; iai_next) + { + sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + + if (sock == -1) continue; + + /* Disable the Nagle algorithm. */ + opt = 1; + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(int)); + + 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(int pi, gpioReport_t *r) +{ + callback_t *p; + uint32_t changed; + int l, g; + +/* + printf("s=%4x f=%4x t=%10u l=%8x\n", + r->seqno, r->flags, r->tick, r->level); +*/ + + if (r->flags == 0) + { + changed = (r->level ^ gLastLevel[pi]) & gNotifyBits[pi]; + + gLastLevel[pi] = r->level; + + p = gCallBackFirst; + + while (p) + { + if (((p->pi) == pi) && (changed & (1<<(p->gpio)))) + { + if ((r->level) & (1<<(p->gpio))) l = 1; else l = 0; + if ((p->edge) ^ l) + { + if (p->ex) (p->f)(pi, p->gpio, l, r->tick, p->user); + else (p->f)(pi, p->gpio, l, r->tick); + } + } + p = p->next; + } + } + else + { + g = (r->flags) & 31; + + p = gCallBackFirst; + + while (p) + { + if (((p->pi) == pi) && ((p->gpio) == g)) + { + if (p->ex) (p->f)(pi, g, PI_TIMEOUT, r->tick, p->user); + else (p->f)(pi, g, PI_TIMEOUT, r->tick); + } + p = p->next; + } + } +} + +static void *pthNotifyThread(void *x) +{ + static int got = 0; + int pi; + int bytes, r; + gpioReport_t report[PI_MAX_REPORTS_PER_READ]; + + pi = *((int*)x); + free(x); /* memory allocated in pigpio_start */ + + while (1) + { + bytes = read(gPigNotify[pi], (char*)&report+got, sizeof(report)-got); + + if (bytes > 0) got += bytes; + else break; + + r = 0; + + while (got >= sizeof(gpioReport_t)) + { + dispatch_notification(pi, &report[r]); + + r++; + + got -= sizeof(gpioReport_t); + } + + /* copy any partial report to start of array */ + + if (got && r) report[0] = report[r]; + } + + fprintf(stderr, "notify thread for pi %d broke with read error %d\n", + pi, bytes); + + while (1) sleep(1); + + return NULL; +} + +static void findNotifyBits(int pi) +{ + callback_t *p; + uint32_t bits = 0; + + p = gCallBackFirst; + + while (p) + { + if (p->pi == pi) bits |= (1<<(p->gpio)); + p = p->next; + } + + if (bits != gNotifyBits[pi]) + { + gNotifyBits[pi] = bits; + pigpio_command(pi, PI_CMD_NB, gPigHandle[pi], gNotifyBits[pi], 1); + } +} + +static void _wfe( + int pi, unsigned user_gpio, unsigned level, uint32_t tick, void *user) +{ + *(int *)user = 1; +} + +static int intCallback( + int pi, unsigned user_gpio, unsigned edge, void *f, void *user, int ex) +{ + static int id = 0; + callback_t *p; + + if ((user_gpio >=0) && (user_gpio < 32) && (edge >=0) && (edge <= 2) && f) + { + /* prevent duplicates */ + + p = gCallBackFirst; + + while (p) + { + if ((p->pi == pi) && + (p->gpio == user_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->pi = pi; + p->gpio = user_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(pi); + + return p->id; + } + + return pigif_bad_malloc; + } + + return pigif_bad_callback; +} + +static int recvMax(int pi, void *buf, int bufsize, int sent) +{ + uint8_t scratch[4096]; + int remaining, fetch, count; + + if (sent < bufsize) count = sent; else count = bufsize; + + if (count) recv(gPigCommand[pi], buf, count, MSG_WAITALL); + + remaining = sent - count; + + while (remaining) + { + fetch = remaining; + if (fetch > sizeof(scratch)) fetch = sizeof(scratch); + recv(gPigCommand[pi], scratch, fetch, MSG_WAITALL); + remaining -= fetch; + } + + return count; +} + +/* 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; + } + } +} + +char *pigpio_error(int errnum) +{ + if (errnum > -1000) return cmdErrStr(errnum); + else + { + switch(errnum) + { + 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 notification in band"; + 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"; + case pigif_unconnected_pi: + return "not connected to Pi"; + case pigif_too_many_pis: + return "too many connected Pis"; + + default: + return "unknown error"; + } + } +} + +unsigned pigpiod_if_version(void) +{ + return PIGPIOD_IF2_VERSION; +} + +pthread_t *start_thread(gpioThreadFunc_t thread_func, void *userdata) +{ + 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, thread_func, userdata)) + { + 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); + free(pth); + } +} + +int pigpio_start(char *addrStr, char *portStr) +{ + int pi; + int *userdata; + + for (pi=0; pi= MAX_PI) return pigif_too_many_pis; + + gPiInUse[pi] = 1; + + pthread_mutex_init(&gCmdMutex[pi], NULL); + + gPigCommand[pi] = pigpioOpenSocket(addrStr, portStr); + + if (gPigCommand[pi] >= 0) + { + gPigNotify[pi] = pigpioOpenSocket(addrStr, portStr); + + if (gPigNotify[pi] >= 0) + { + gPigHandle[pi] = pigpio_notify(pi); + + if (gPigHandle[pi] < 0) return pigif_bad_noib; + else + { + gLastLevel[pi] = read_bank_1(pi); + + /* must be freed by pthNotifyThread */ + userdata = malloc(sizeof(*userdata)); + *userdata = pi; + + gPthNotify[pi] = start_thread(pthNotifyThread, userdata); + + if (gPthNotify[pi]) return pi; + else return pigif_notify_failed; + + } + } + else return gPigNotify[pi]; + } + else return gPigCommand[pi]; +} + +void pigpio_stop(int pi) +{ + if ((pi < 0) || (pi >= MAX_PI) || !gPiInUse[pi]) return; + + if (gPthNotify[pi]) + { + stop_thread(gPthNotify[pi]); + gPthNotify[pi] = 0; + } + + if (gPigCommand[pi] >= 0) + { + if (gPigHandle[pi] >= 0) + { + pigpio_command(pi, PI_CMD_NC, gPigHandle[pi], 0, 1); + gPigHandle[pi] = -1; + } + + close(gPigCommand[pi]); + gPigCommand[pi] = -1; + } + + if (gPigNotify[pi] >= 0) + { + close(gPigNotify[pi]); + gPigNotify[pi] = -1; + } + + gPiInUse[pi] = 0; +} + +int set_mode(int pi, unsigned gpio, unsigned mode) + {return pigpio_command(pi, PI_CMD_MODES, gpio, mode, 1);} + +int get_mode(int pi, unsigned gpio) + {return pigpio_command(pi, PI_CMD_MODEG, gpio, 0, 1);} + +int set_pull_up_down(int pi, unsigned gpio, unsigned pud) + {return pigpio_command(pi, PI_CMD_PUD, gpio, pud, 1);} + +int gpio_read(int pi, unsigned gpio) + {return pigpio_command(pi, PI_CMD_READ, gpio, 0, 1);} + +int gpio_write(int pi, unsigned gpio, unsigned level) + {return pigpio_command(pi, PI_CMD_WRITE, gpio, level, 1);} + +int set_PWM_dutycycle(int pi, unsigned user_gpio, unsigned dutycycle) + {return pigpio_command(pi, PI_CMD_PWM, user_gpio, dutycycle, 1);} + +int get_PWM_dutycycle(int pi, unsigned user_gpio) + {return pigpio_command(pi, PI_CMD_GDC, user_gpio, 0, 1);} + +int set_PWM_range(int pi, unsigned user_gpio, unsigned range) + {return pigpio_command(pi, PI_CMD_PRS, user_gpio, range, 1);} + +int get_PWM_range(int pi, unsigned user_gpio) + {return pigpio_command(pi, PI_CMD_PRG, user_gpio, 0, 1);} + +int get_PWM_real_range(int pi, unsigned user_gpio) + {return pigpio_command(pi, PI_CMD_PRRG, user_gpio, 0, 1);} + +int set_PWM_frequency(int pi, unsigned user_gpio, unsigned frequency) + {return pigpio_command(pi, PI_CMD_PFS, user_gpio, frequency, 1);} + +int get_PWM_frequency(int pi, unsigned user_gpio) + {return pigpio_command(pi, PI_CMD_PFG, user_gpio, 0, 1);} + +int set_servo_pulsewidth(int pi, unsigned user_gpio, unsigned pulsewidth) + {return pigpio_command(pi, PI_CMD_SERVO, user_gpio, pulsewidth, 1);} + +int get_servo_pulsewidth(int pi, unsigned user_gpio) + {return pigpio_command(pi, PI_CMD_GPW, user_gpio, 0, 1);} + +int notify_open(int pi) + {return pigpio_command(pi, PI_CMD_NO, 0, 0, 1);} + +int notify_begin(int pi, unsigned handle, uint32_t bits) + {return pigpio_command(pi, PI_CMD_NB, handle, bits, 1);} + +int notify_pause(int pi, unsigned handle) + {return pigpio_command(pi, PI_CMD_NB, handle, 0, 1);} + +int notify_close(int pi, unsigned handle) + {return pigpio_command(pi, PI_CMD_NC, handle, 0, 1);} + +int set_watchdog(int pi, unsigned user_gpio, unsigned timeout) + {return pigpio_command(pi, PI_CMD_WDOG, user_gpio, timeout, 1);} + +uint32_t read_bank_1(int pi) + {return pigpio_command(pi, PI_CMD_BR1, 0, 0, 1);} + +uint32_t read_bank_2(int pi) + {return pigpio_command(pi, PI_CMD_BR2, 0, 0, 1);} + +int clear_bank_1(int pi, uint32_t levels) + {return pigpio_command(pi, PI_CMD_BC1, levels, 0, 1);} + +int clear_bank_2(int pi, uint32_t levels) + {return pigpio_command(pi, PI_CMD_BC2, levels, 0, 1);} + +int set_bank_1(int pi, uint32_t levels) + {return pigpio_command(pi, PI_CMD_BS1, levels, 0, 1);} + +int set_bank_2(int pi, uint32_t levels) + {return pigpio_command(pi, PI_CMD_BS2, levels, 0, 1);} + +int hardware_clock(int pi, unsigned gpio, unsigned frequency) + {return pigpio_command(pi, PI_CMD_HC, gpio, frequency, 1);} + +int hardware_PWM(int pi, unsigned gpio, unsigned frequency, uint32_t dutycycle) +{ + gpioExtent_t ext[1]; + + /* + p1=gpio + p2=frequency + p3=4 + ## extension ## + uint32_t dutycycle + */ + + ext[0].size = sizeof(dutycycle); + ext[0].ptr = &dutycycle; + + return pigpio_command_ext( + pi, PI_CMD_HP, gpio, frequency, sizeof(dutycycle), 1, ext, 1); +} + +uint32_t get_current_tick(int pi) + {return pigpio_command(pi, PI_CMD_TICK, 0, 0, 1);} + +uint32_t get_hardware_revision(int pi) + {return pigpio_command(pi, PI_CMD_HWVER, 0, 0, 1);} + +uint32_t get_pigpio_version(int pi) + {return pigpio_command(pi, PI_CMD_PIGPV, 0, 0, 1);} + +int wave_clear(int pi) + {return pigpio_command(pi, PI_CMD_WVCLR, 0, 0, 1);} + +int wave_add_new(int pi) + {return pigpio_command(pi, PI_CMD_WVNEW, 0, 0, 1);} + +int wave_add_generic(int pi, unsigned numPulses, gpioPulse_t *pulses) +{ + gpioExtent_t ext[1]; + + /* + p1=0 + p2=0 + p3=pulses*sizeof(gpioPulse_t) + ## extension ## + gpioPulse_t[] pulses + */ + + if (!numPulses) return 0; + + ext[0].size = numPulses * sizeof(gpioPulse_t); + ext[0].ptr = pulses; + + return pigpio_command_ext( + pi, PI_CMD_WVAG, 0, 0, ext[0].size, 1, ext, 1); +} + +int wave_add_serial( + int pi, unsigned user_gpio, unsigned baud, uint32_t databits, + uint32_t stophalfbits, uint32_t offset, unsigned numChar, char *str) +{ + uint8_t buf[12]; + gpioExtent_t ext[2]; + + /* + p1=user_gpio + p2=baud + p3=len+12 + ## extension ## + uint32_t databits + uint32_t stophalfbits + uint32_t offset + char[len] str + */ + + if (!numChar) return 0; + + memcpy(buf, &databits, 4); + memcpy(buf+4, &stophalfbits, 4); + memcpy(buf+8, &offset, 4); + + ext[0].size = sizeof(buf); + ext[0].ptr = buf; + + ext[1].size = numChar; + ext[1].ptr = str; + + return pigpio_command_ext(pi, PI_CMD_WVAS, + user_gpio, baud, numChar+sizeof(buf), 2, ext, 1); +} + +int wave_create(int pi) + {return pigpio_command(pi, PI_CMD_WVCRE, 0, 0, 1);} + +int wave_delete(int pi, unsigned wave_id) + {return pigpio_command(pi, PI_CMD_WVDEL, wave_id, 0, 1);} + +int wave_tx_start(int pi) /* DEPRECATED */ + {return pigpio_command(pi, PI_CMD_WVGO, 0, 0, 1);} + +int wave_tx_repeat(int pi) /* DEPRECATED */ + {return pigpio_command(pi, PI_CMD_WVGOR, 0, 0, 1);} + +int wave_send_once(int pi, unsigned wave_id) + {return pigpio_command(pi, PI_CMD_WVTX, wave_id, 0, 1);} + +int wave_send_repeat(int pi, unsigned wave_id) + {return pigpio_command(pi, PI_CMD_WVTXR, wave_id, 0, 1);} + +int wave_chain(int pi, char *buf, unsigned bufSize) +{ + gpioExtent_t ext[1]; + + /* + p1=0 + p2=0 + p3=bufSize + ## extension ## + char buf[bufSize] + */ + + ext[0].size = bufSize; + ext[0].ptr = buf; + + return pigpio_command_ext + (pi, PI_CMD_WVCHA, 0, 0, bufSize, 1, ext, 1); +} + +int wave_tx_busy(int pi) + {return pigpio_command(pi, PI_CMD_WVBSY, 0, 0, 1);} + +int wave_tx_stop(int pi) + {return pigpio_command(pi, PI_CMD_WVHLT, 0, 0, 1);} + +int wave_get_micros(int pi) + {return pigpio_command(pi, PI_CMD_WVSM, 0, 0, 1);} + +int wave_get_high_micros(int pi) + {return pigpio_command(pi, PI_CMD_WVSM, 1, 0, 1);} + +int wave_get_max_micros(int pi) + {return pigpio_command(pi, PI_CMD_WVSM, 2, 0, 1);} + +int wave_get_pulses(int pi) + {return pigpio_command(pi, PI_CMD_WVSP, 0, 0, 1);} + +int wave_get_high_pulses(int pi) + {return pigpio_command(pi, PI_CMD_WVSP, 1, 0, 1);} + +int wave_get_max_pulses(int pi) + {return pigpio_command(pi, PI_CMD_WVSP, 2, 0, 1);} + +int wave_get_cbs(int pi) + {return pigpio_command(pi, PI_CMD_WVSC, 0, 0, 1);} + +int wave_get_high_cbs(int pi) + {return pigpio_command(pi, PI_CMD_WVSC, 1, 0, 1);} + +int wave_get_max_cbs(int pi) + {return pigpio_command(pi, PI_CMD_WVSC, 2, 0, 1);} + +int gpio_trigger(int pi, unsigned user_gpio, unsigned pulseLen, uint32_t level) +{ + gpioExtent_t ext[1]; + + /* + p1=user_gpio + p2=pulseLen + p3=4 + ## extension ## + unsigned level + */ + + ext[0].size = sizeof(uint32_t); + ext[0].ptr = &level; + + return pigpio_command_ext( + pi, PI_CMD_TRIG, user_gpio, pulseLen, 4, 1, ext, 1); +} + +int set_glitch_filter(int pi, unsigned user_gpio, unsigned steady) + {return pigpio_command(pi, PI_CMD_FG, user_gpio, steady, 1);} + +int set_noise_filter(int pi, unsigned user_gpio, unsigned steady, unsigned active) +{ + gpioExtent_t ext[1]; + + /* + p1=user_gpio + p2=steady + p3=4 + ## extension ## + unsigned active + */ + + ext[0].size = sizeof(uint32_t); + ext[0].ptr = &active; + + return pigpio_command_ext( + pi, PI_CMD_FN, user_gpio, steady, 4, 1, ext, 1); +} + +int store_script(int pi, char *script) +{ + unsigned len; + gpioExtent_t ext[1]; + + /* + p1=0 + p2=0 + p3=len + ## extension ## + char[len] script + */ + + len = strlen(script); + + if (!len) return 0; + + ext[0].size = len; + ext[0].ptr = script; + + return pigpio_command_ext(pi, PI_CMD_PROC, 0, 0, len, 1, ext, 1); +} + +int run_script(int pi, unsigned script_id, unsigned numPar, uint32_t *param) +{ + gpioExtent_t ext[1]; + + /* + p1=script id + p2=0 + p3=numPar * 4 + ## extension ## + uint32_t[numPar] pars + */ + + ext[0].size = 4 * numPar; + ext[0].ptr = param; + + return pigpio_command_ext + (pi, PI_CMD_PROCR, script_id, 0, numPar*4, 1, ext, 1); +} + +int script_status(int pi, unsigned script_id, uint32_t *param) +{ + int status; + uint32_t p[PI_MAX_SCRIPT_PARAMS+1]; /* space for script status */ + + status = pigpio_command(pi, PI_CMD_PROCP, script_id, 0, 0); + + if (status > 0) + { + recvMax(pi, p, sizeof(p), status); + status = p[0]; + if (param) memcpy(param, p+1, sizeof(p)-4); + } + + _pmu(pi); + + return status; +} + +int stop_script(int pi, unsigned script_id) + {return pigpio_command(pi, PI_CMD_PROCS, script_id, 0, 1);} + +int delete_script(int pi, unsigned script_id) + {return pigpio_command(pi, PI_CMD_PROCD, script_id, 0, 1);} + +int bb_serial_read_open(int pi, unsigned user_gpio, unsigned baud, uint32_t bbBits) +{ + gpioExtent_t ext[1]; + + /* + p1=user_gpio + p2=baud + p3=4 + ## extension ## + unsigned bbBits + */ + + ext[0].size = sizeof(uint32_t); + ext[0].ptr = &bbBits; + + return pigpio_command_ext( + pi, PI_CMD_SLRO, user_gpio, baud, 4, 1, ext, 1); +} + +int bb_serial_read(int pi, unsigned user_gpio, void *buf, size_t bufSize) +{ + int bytes; + + bytes = pigpio_command(pi, PI_CMD_SLR, user_gpio, bufSize, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, buf, bufSize, bytes); + } + + _pmu(pi); + + return bytes; +} + +int bb_serial_read_close(int pi, unsigned user_gpio) + {return pigpio_command(pi, PI_CMD_SLRC, user_gpio, 0, 1);} + +int bb_serial_invert(int pi, unsigned user_gpio, unsigned invert) + {return pigpio_command(pi, PI_CMD_SLRI, user_gpio, invert, 1);} + +int i2c_open(int pi, unsigned i2c_bus, unsigned i2c_addr, uint32_t i2c_flags) +{ + gpioExtent_t ext[1]; + + /* + p1=i2c_bus + p2=i2c_addr + p3=4 + ## extension ## + uint32_t i2c_flags + */ + + ext[0].size = sizeof(uint32_t); + ext[0].ptr = &i2c_flags; + + return pigpio_command_ext + (pi, PI_CMD_I2CO, i2c_bus, i2c_addr, 4, 1, ext, 1); +} + +int i2c_close(int pi, unsigned handle) + {return pigpio_command(pi, PI_CMD_I2CC, handle, 0, 1);} + +int i2c_write_quick(int pi, unsigned handle, unsigned bit) + {return pigpio_command(pi, PI_CMD_I2CWQ, handle, bit, 1);} + +int i2c_write_byte(int pi, unsigned handle, unsigned val) + {return pigpio_command(pi, PI_CMD_I2CWS, handle, val, 1);} + +int i2c_read_byte(int pi, unsigned handle) + {return pigpio_command(pi, PI_CMD_I2CRS, handle, 0, 1);} + +int i2c_write_byte_data(int pi, unsigned handle, unsigned reg, uint32_t val) +{ + gpioExtent_t ext[1]; + + /* + p1=handle + p2=reg + p3=4 + ## extension ## + uint32_t val + */ + + ext[0].size = sizeof(uint32_t); + ext[0].ptr = &val; + + return pigpio_command_ext + (pi, PI_CMD_I2CWB, handle, reg, 4, 1, ext, 1); +} + +int i2c_write_word_data(int pi, unsigned handle, unsigned reg, uint32_t val) +{ + gpioExtent_t ext[1]; + + /* + p1=handle + p2=reg + p3=4 + ## extension ## + uint32_t val + */ + + ext[0].size = sizeof(uint32_t); + ext[0].ptr = &val; + + return pigpio_command_ext + (pi, PI_CMD_I2CWW, handle, reg, 4, 1, ext, 1); +} + +int i2c_read_byte_data(int pi, unsigned handle, unsigned reg) + {return pigpio_command(pi, PI_CMD_I2CRB, handle, reg, 1);} + +int i2c_read_word_data(int pi, unsigned handle, unsigned reg) + {return pigpio_command(pi, PI_CMD_I2CRW, handle, reg, 1);} + +int i2c_process_call(int pi, unsigned handle, unsigned reg, uint32_t val) +{ + gpioExtent_t ext[1]; + + /* + p1=handle + p2=reg + p3=4 + ## extension ## + uint32_t val + */ + + ext[0].size = sizeof(uint32_t); + ext[0].ptr = &val; + + return pigpio_command_ext + (pi, PI_CMD_I2CPK, handle, reg, 4, 1, ext, 1); +} + +int i2c_write_block_data( + int pi, unsigned handle, unsigned reg, char *buf, unsigned count) +{ + gpioExtent_t ext[1]; + + /* + p1=handle + p2=reg + p3=count + ## extension ## + char buf[count] + */ + + ext[0].size = count; + ext[0].ptr = buf; + + return pigpio_command_ext + (pi, PI_CMD_I2CWK, handle, reg, count, 1, ext, 1); +} + +int i2c_read_block_data(int pi, unsigned handle, unsigned reg, char *buf) +{ + int bytes; + + bytes = pigpio_command(pi, PI_CMD_I2CRK, handle, reg, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, buf, 32, bytes); + } + + _pmu(pi); + + return bytes; +} + +int i2c_block_process_call( + int pi, unsigned handle, unsigned reg, char *buf, unsigned count) +{ + int bytes; + gpioExtent_t ext[1]; + + /* + p1=handle + p2=reg + p3=count + ## extension ## + char buf[count] + */ + + ext[0].size = count; + ext[0].ptr = buf; + + bytes = pigpio_command_ext + (pi, PI_CMD_I2CPK, handle, reg, count, 1, ext, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, buf, 32, bytes); + } + + _pmu(pi); + + return bytes; +} + +int i2c_read_i2c_block_data( + int pi, unsigned handle, unsigned reg, char *buf, uint32_t count) +{ + int bytes; + gpioExtent_t ext[1]; + + /* + p1=handle + p2=reg + p3=4 + ## extension ## + uint32_t count + */ + + ext[0].size = sizeof(uint32_t); + ext[0].ptr = &count; + + bytes = pigpio_command_ext + (pi, PI_CMD_I2CRI, handle, reg, 4, 1, ext, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, buf, count, bytes); + } + + _pmu(pi); + + return bytes; +} + + +int i2c_write_i2c_block_data( + int pi, unsigned handle, unsigned reg, char *buf, unsigned count) +{ + gpioExtent_t ext[1]; + + /* + p1=handle + p2=reg + p3=count + ## extension ## + char buf[count] + */ + + ext[0].size = count; + ext[0].ptr = buf; + + return pigpio_command_ext + (pi, PI_CMD_I2CWI, handle, reg, count, 1, ext, 1); +} + +int i2c_read_device(int pi, unsigned handle, char *buf, unsigned count) +{ + int bytes; + + bytes = pigpio_command(pi, PI_CMD_I2CRD, handle, count, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, buf, count, bytes); + } + + _pmu(pi); + + return bytes; +} + +int i2c_write_device(int pi, unsigned handle, char *buf, unsigned count) +{ + gpioExtent_t ext[1]; + + /* + p1=handle + p2=0 + p3=count + ## extension ## + char buf[count] + */ + + ext[0].size = count; + ext[0].ptr = buf; + + return pigpio_command_ext + (pi, PI_CMD_I2CWD, handle, 0, count, 1, ext, 1); +} + +int i2c_zip( + int pi, + unsigned handle, + char *inBuf, + unsigned inLen, + char *outBuf, + unsigned outLen) +{ + int bytes; + gpioExtent_t ext[1]; + + /* + p1=handle + p2=0 + p3=inLen + ## extension ## + char inBuf[inLen] + */ + + ext[0].size = inLen; + ext[0].ptr = inBuf; + + bytes = pigpio_command_ext + (pi, PI_CMD_I2CZ, handle, 0, inLen, 1, ext, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, outBuf, outLen, bytes); + } + + _pmu(pi); + + return bytes; +} + +int bb_i2c_open(int pi, unsigned SDA, unsigned SCL, unsigned baud) +{ + gpioExtent_t ext[1]; + + /* + p1=SDA + p2=SCL + p3=4 + ## extension ## + uint32_t baud + */ + + ext[0].size = sizeof(uint32_t); + ext[0].ptr = &baud; + + return pigpio_command_ext + (pi, PI_CMD_BI2CO, SDA, SCL, 4, 1, ext, 1); +} + +int bb_i2c_close(int pi, unsigned SDA) + {return pigpio_command(pi, PI_CMD_BI2CC, SDA, 0, 1);} + +int bb_i2c_zip( + int pi, + unsigned SDA, + char *inBuf, + unsigned inLen, + char *outBuf, + unsigned outLen) +{ + int bytes; + gpioExtent_t ext[1]; + + /* + p1=SDA + p2=0 + p3=inLen + ## extension ## + char inBuf[inLen] + */ + + ext[0].size = inLen; + ext[0].ptr = inBuf; + + bytes = pigpio_command_ext + (pi, PI_CMD_BI2CZ, SDA, 0, inLen, 1, ext, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, outBuf, outLen, bytes); + } + + _pmu(pi); + + return bytes; +} + +int spi_open(int pi, unsigned channel, unsigned speed, uint32_t flags) +{ + gpioExtent_t ext[1]; + + /* + p1=channel + p2=speed + p3=4 + ## extension ## + uint32_t flags + */ + + ext[0].size = sizeof(uint32_t); + ext[0].ptr = &flags; + + return pigpio_command_ext + (pi, PI_CMD_SPIO, channel, speed, 4, 1, ext, 1); +} + +int spi_close(int pi, unsigned handle) + {return pigpio_command(pi, PI_CMD_SPIC, handle, 0, 1);} + +int spi_read(int pi, unsigned handle, char *buf, unsigned count) +{ + int bytes; + + bytes = pigpio_command + (pi, PI_CMD_SPIR, handle, count, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, buf, count, bytes); + } + + _pmu(pi); + + return bytes; +} + +int spi_write(int pi, unsigned handle, char *buf, unsigned count) +{ + gpioExtent_t ext[1]; + + /* + p1=handle + p2=0 + p3=count + ## extension ## + char buf[count] + */ + + ext[0].size = count; + ext[0].ptr = buf; + + return pigpio_command_ext + (pi, PI_CMD_SPIW, handle, 0, count, 1, ext, 1); +} + +int spi_xfer(int pi, unsigned handle, char *txBuf, char *rxBuf, unsigned count) +{ + int bytes; + gpioExtent_t ext[1]; + + /* + p1=handle + p2=0 + p3=count + ## extension ## + char buf[count] + */ + + ext[0].size = count; + ext[0].ptr = txBuf; + + bytes = pigpio_command_ext + (pi, PI_CMD_SPIX, handle, 0, count, 1, ext, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, rxBuf, count, bytes); + } + + _pmu(pi); + + return bytes; +} + +int serial_open(int pi, char *dev, unsigned baud, unsigned flags) +{ + int len; + gpioExtent_t ext[1]; + + len = strlen(dev); + + /* + p1=baud + p2=flags + p3=len + ## extension ## + char dev[len] + */ + + ext[0].size = len; + ext[0].ptr = dev; + + return pigpio_command_ext + (pi, PI_CMD_SERO, baud, flags, len, 1, ext, 1); +} + +int serial_close(int pi, unsigned handle) + {return pigpio_command(pi, PI_CMD_SERC, handle, 0, 1);} + +int serial_write_byte(int pi, unsigned handle, unsigned val) + {return pigpio_command(pi, PI_CMD_SERWB, handle, val, 1);} + +int serial_read_byte(int pi, unsigned handle) + {return pigpio_command(pi, PI_CMD_SERRB, handle, 0, 1);} + +int serial_write(int pi, unsigned handle, char *buf, unsigned count) +{ + gpioExtent_t ext[1]; + + /* + p1=handle + p2=0 + p3=count + ## extension ## + char buf[count] + */ + + ext[0].size = count; + ext[0].ptr = buf; + + return pigpio_command_ext + (pi, PI_CMD_SERW, handle, 0, count, 1, ext, 1); +} + +int serial_read(int pi, unsigned handle, char *buf, unsigned count) +{ + int bytes; + + bytes = pigpio_command + (pi, PI_CMD_SERR, handle, count, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, buf, count, bytes); + } + + _pmu(pi); + + return bytes; +} + +int serial_data_available(int pi, unsigned handle) + {return pigpio_command(pi, PI_CMD_SERDA, handle, 0, 1);} + +int custom_1(int pi, unsigned arg1, unsigned arg2, char *argx, unsigned count) +{ + gpioExtent_t ext[1]; + + /* + p1=arg1 + p2=arg2 + p3=count + ## extension ## + char argx[count] + */ + + ext[0].size = count; + ext[0].ptr = argx; + + return pigpio_command_ext( + pi, PI_CMD_CF1, arg1, arg2, count, 1, ext, 1); +} + + +int custom_2(int pi, unsigned arg1, char *argx, unsigned count, + char *retBuf, uint32_t retMax) +{ + int bytes; + gpioExtent_t ext[1]; + + /* + p1=arg1 + p2=retMax + p3=count + ## extension ## + char argx[count] + */ + + ext[0].size = count; + ext[0].ptr = argx; + + bytes = pigpio_command_ext + (pi, PI_CMD_CF2, arg1, retMax, count, 1, ext, 0); + + if (bytes > 0) + { + bytes = recvMax(pi, retBuf, retMax, bytes); + } + + _pmu(pi); + + return bytes; +} + +int callback(int pi, unsigned user_gpio, unsigned edge, CBFunc_t f) + {return intCallback(pi, user_gpio, edge, f, 0, 0);} + +int callback_ex( + int pi, unsigned user_gpio, unsigned edge, CBFuncEx_t f, void *user) + {return intCallback(pi, user_gpio, edge, f, user, 1);} + +int callback_cancel(unsigned id) +{ + callback_t *p; + int pi; + + p = gCallBackFirst; + + while (p) + { + if (p->id == id) + { + pi = p->pi; + + 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(pi); + + return 0; + } + p = p->next; + } + return pigif_callback_not_found; +} + +int wait_for_edge(int pi, unsigned user_gpio, unsigned edge, double timeout) +{ + int triggered = 0; + int id; + double due; + + if ((pi < 0) || (pi >= MAX_PI) || !gPiInUse[pi]) + return pigif_unconnected_pi; + + if (timeout <= 0.0) return 0; + + due = time_time() + timeout; + + id = callback_ex(pi, user_gpio, edge, _wfe, &triggered); + + while (!triggered && (time_time() < due)) time_sleep(0.1); + + callback_cancel(id); + + return triggered; +} + diff --git a/pigpiod_if2.h b/pigpiod_if2.h new file mode 100644 index 0000000..45aeb0f --- /dev/null +++ b/pigpiod_if2.h @@ -0,0 +1,3094 @@ +/* +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 +*/ + +#ifndef PIGPIOD_IF2_H +#define PIGPIOD_IF2_H + +#include "pigpio.h" + +#define PIGPIOD_IF2_VERSION 1 + +/*TEXT + +pigpiod_if2 is a C library for the Raspberry which allows control +of the gpios via the socket interface to the pigpio daemon. + +*Features* + +o PWM on any of gpios 0-31 + +o servo pulses on any of gpios 0-31 + +o callbacks when any of gpios 0-31 change state + +o callbacks at timed intervals + +o reading/writing all of the gpios in a bank as one operation + +o individually setting gpio modes, reading and writing + +o notifications when any of gpios 0-31 change state + +o the construction of output waveforms with microsecond timing + +o rudimentary permission control over gpios + +o a simple interface to start and stop new threads + +o I2C, SPI, and serial link wrappers + +o creating and running scripts on the pigpio daemon + +*gpios* + +ALL gpios are identified by their Broadcom number. + +*Notes* + +The PWM and servo pulses are timed using the DMA and PWM/PCM peripherals. + +*Usage* + +Include in your source files. + +Assuming your source is in prog.c use the following command to build + +. . +gcc -Wall -pthread -o prog prog.c -lpigpiod_if2 -lrt +. . + +to run make sure the pigpio daemon is running + +. . +sudo pigpiod + + ./prog # sudo is not required to run programs linked to pigpiod_if2 +. . + +For examples see x_pigpiod_if2.c within the pigpio archive file. + +*Notes* + +All the functions which return an int return < 0 on error + +TEXT*/ + +/*OVERVIEW + +ESSENTIAL + +pigpio_start Connects to a pigpio daemon +pigpio_stop Disconnects from a pigpio daemon + +BEGINNER + +set_mode Set a gpio mode +get_mode Get a gpio mode + +set_pull_up_down Set/clear gpio pull up/down resistor + +gpio_read Read a gpio +gpio_write Write a gpio + +set_PWM_dutycycle Start/stop PWM pulses on a gpio +get_PWM_dutycycle Get the PWM dutycycle in use on a gpio + +set_servo_pulsewidth Start/stop servo pulses on a gpio +get_servo_pulsewidth Get the servo pulsewidth in use on a gpio + +callback Create gpio level change callback +callback_ex Create gpio level change callback +callback_cancel Cancel a callback +wait_for_edge Wait for gpio level change + +INTERMEDIATE + +gpio_trigger Send a trigger pulse to a gpio. + +set_watchdog Set a watchdog on a gpio. + +set_PWM_range Configure PWM range for a gpio +get_PWM_range Get configured PWM range for a gpio + +set_PWM_frequency Configure PWM frequency for a gpio +get_PWM_frequency Get configured PWM frequency for a gpio + +read_bank_1 Read all gpios in bank 1 +read_bank_2 Read all gpios in bank 2 + +clear_bank_1 Clear selected gpios in bank 1 +clear_bank_2 Clear selected gpios in bank 2 + +set_bank_1 Set selected gpios in bank 1 +set_bank_2 Set selected gpios in bank 2 + +start_thread Start a new thread +stop_thread Stop a previously started thread + +ADVANCED + +get_PWM_real_range Get underlying PWM range for a gpio + +notify_open Request a notification handle +notify_begin Start notifications for selected gpios +notify_pause Pause notifications +notify_close Close a notification + +bb_serial_read_open Opens a gpio for bit bang serial reads +bb_serial_read Reads bit bang serial data from a gpio +bb_serial_read_close Closes a gpio for bit bang serial reads +bb_serial_invert Invert serial logic (1 invert, 0 normal) + +hardware_clock Start hardware clock on supported gpios +hardware_PWM Start hardware PWM on supported gpios + +set_glitch_filter Set a glitch filter on a gpio +set_noise_filter Set a noise filter on a gpio + +SCRIPTS + +store_script Store a script +run_script Run a stored script +script_status Get script status and parameters +stop_script Stop a running script +delete_script Delete a stored script + +WAVES + +wave_clear Deletes all waveforms + +wave_add_new Starts a new waveform +wave_add_generic Adds a series of pulses to the waveform +wave_add_serial Adds serial data to the waveform + +wave_create Creates a waveform from added data +wave_delete Deletes one or more waveforms + +wave_send_once Transmits a waveform once +wave_send_repeat Transmits a waveform repeatedly + +wave_chain Transmits a chain of waveforms + +wave_tx_busy Checks to see if the waveform has ended +wave_tx_stop Aborts the current waveform + +wave_get_micros Length in microseconds of the current waveform +wave_get_high_micros Length of longest waveform so far +wave_get_max_micros Absolute maximum allowed micros + +wave_get_pulses Length in pulses of the current waveform +wave_get_high_pulses Length of longest waveform so far +wave_get_max_pulses Absolute maximum allowed pulses + +wave_get_cbs Length in cbs of the current waveform +wave_get_high_cbs Length of longest waveform so far +wave_get_max_cbs Absolute maximum allowed cbs + +I2C + +i2c_open Opens an I2C device +i2c_close Closes an I2C device + +i2c_write_quick smbus write quick +i2c_write_byte smbus write byte +i2c_read_byte smbus read byte +i2c_write_byte_data smbus write byte data +i2c_write_word_data smbus write word data +i2c_read_byte_data smbus read byte data +i2c_read_word_data smbus read word data +i2c_process_call smbus process call +i2c_write_block_data smbus write block data +i2c_read_block_data smbus read block data +i2c_block_process_call smbus block process call + +i2c_write_i2c_block_data smbus write I2C block data +i2c_read_i2c_block_data smbus read I2C block data + +i2c_read_device Reads the raw I2C device +i2c_write_device Writes the raw I2C device + +i2c_zip Performs multiple I2C transactions + +bb_i2c_open Opens gpios for bit banging I2C +bb_i2c_close Closes gpios for bit banging I2C +bb_i2c_zip Performs multiple bit banged I2C transactions + +SPI + +spi_open Opens a SPI device +spi_close Closes a SPI device + +spi_read Reads bytes from a SPI device +spi_write Writes bytes to a SPI device +spi_xfer Transfers bytes with a SPI device + +SERIAL + +serial_open Opens a serial device (/dev/tty*) +serial_close Closes a serial device + +serial_write_byte Writes a byte to a serial device +serial_read_byte Reads a byte from a serial device +serial_write Writes bytes to a serial device +serial_read Reads bytes from a serial device + +serial_data_available Returns number of bytes ready to be read + +CUSTOM + +custom_1 User custom function 1 +custom_2 User custom function 2 + +UTILITIES + +get_current_tick Get current tick (microseconds) + +get_hardware_revision Get hardware revision +get_pigpio_version Get the pigpio version +pigpiod_if_version Get the pigpiod_if2 version + +pigpio_error Get a text description of an error code. + +time_sleep Sleeps for a float number of seconds +time_time Float number of seconds since the epoch + +OVERVIEW*/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*CBFunc_t) + (int pi, unsigned user_gpio, unsigned level, uint32_t tick); + +typedef void (*CBFuncEx_t) + (int pi, unsigned user_gpio, unsigned level, uint32_t tick, void * user); + +typedef struct callback_s callback_t; + +/*F*/ +double time_time(void); +/*D +Return the current time in seconds since the Epoch. +D*/ + +/*F*/ +void time_sleep(double seconds); +/*D +Delay execution for a given number of seconds. + +. . +seconds: the number of seconds to delay. +. . +D*/ + +/*F*/ +char *pigpio_error(int errnum); +/*D +Return a text description for an error code. + +. . +errnum: the error code. +. . +D*/ + +/*F*/ +unsigned pigpiod_if_version(void); +/*D +Return the pigpiod_if2 version. +D*/ + +/*F*/ +pthread_t *start_thread(gpioThreadFunc_t thread_func, void *userdata); +/*D +Starts a new thread of execution with thread_func as the main routine. + +. . +thread_func: the main function for the new thread. + userdata: a pointer to an arbitrary argument. +. . + +Returns a pointer to pthread_t if OK, otherwise NULL. + +The function is passed the single argument userdata. + +The thread can be cancelled by passing the pointer to pthread_t to +[*stop_thread*]. +D*/ + +/*F*/ +void stop_thread(pthread_t *pth); +/*D +Cancels the thread pointed at by pth. + +. . +pth: the thread to be stopped. +. . + +No value is returned. + +The thread to be stopped should have been started with [*start_thread*]. +D*/ + +/*F*/ +int pigpio_start(char *addrStr, char *portStr); +/*D +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 overridden 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 overridden by the PIGPIO_PORT environment + variable. +. . + +Returns an integer value greater than or equal to zero if OK. + +This value is passed to the GPIO routines to specify the Pi +to be operated on. +D*/ + +/*F*/ +void pigpio_stop(int pi); +/*D +Terminates the connection to a pigpio daemon and releases +resources used by the library. + +. . +pi: 0- (as returned by [*pigpio_start*]). +. . +D*/ + +/*F*/ +int set_mode(int pi, unsigned gpio, unsigned mode); +/*D +Set the gpio mode. + +. . + pi: 0- (as returned by [*pigpio_start*]). +gpio: 0-53. +mode: PI_INPUT, PI_OUTPUT, PI_ALT0, _ALT1, + PI_ALT2, PI_ALT3, PI_ALT4, PI_ALT5. +. . + +Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_MODE, +or PI_NOT_PERMITTED. +D*/ + +/*F*/ +int get_mode(int pi, unsigned gpio); +/*D +Get the gpio mode. + +. . + pi: 0- (as returned by [*pigpio_start*]). +gpio: 0-53. +. . + +Returns the gpio mode if OK, otherwise PI_BAD_GPIO. +D*/ + +/*F*/ +int set_pull_up_down(int pi, unsigned gpio, unsigned pud); +/*D +Set or clear the gpio pull-up/down resistor. + +. . + pi: 0- (as returned by [*pigpio_start*]). +gpio: 0-53. + pud: PI_PUD_UP, PI_PUD_DOWN, PI_PUD_OFF. +. . + +Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_PUD, +or PI_NOT_PERMITTED. +D*/ + +/*F*/ +int gpio_read(int pi, unsigned gpio); +/*D +Read the gpio level. + +. . + pi: 0- (as returned by [*pigpio_start*]). +gpio:0-53. +. . + +Returns the gpio level if OK, otherwise PI_BAD_GPIO. +D*/ + +/*F*/ +int gpio_write(int pi, unsigned gpio, unsigned level); +/*D +Write the gpio level. + +. . + pi: 0- (as returned by [*pigpio_start*]). + gpio: 0-53. +level: 0, 1. +. . + +Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_LEVEL, +or PI_NOT_PERMITTED. + +Notes + +If PWM or servo pulses are active on the gpio they are switched off. +D*/ + +/*F*/ +int set_PWM_dutycycle(int pi, unsigned user_gpio, unsigned dutycycle); +/*D +Start (non-zero dutycycle) or stop (0) PWM pulses on the gpio. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. +dutycycle: 0-range (range defaults to 255). +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_DUTYCYCLE, +or PI_NOT_PERMITTED. +Notes + +The [*set_PWM_range*] function may be used to change the +default range of 255. +D*/ + +/*F*/ +int get_PWM_dutycycle(int pi, unsigned user_gpio); +/*D +Return the PWM dutycycle in use on a gpio. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO or PI_NOT_PWM_GPIO. + +For normal PWM the dutycycle will be out of the defined range +for the gpio (see [*get_PWM_range*]). + +If a hardware clock is active on the gpio the reported dutycycle +will be 500000 (500k) out of 1000000 (1M). + +If hardware PWM is active on the gpio the reported dutycycle +will be out of a 1000000 (1M). +D*/ + +/*F*/ +int set_PWM_range(int pi, unsigned user_gpio, unsigned range); +/*D +Set the range of PWM values to be used on the gpio. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. + range: 25-40000. +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_DUTYRANGE, +or PI_NOT_PERMITTED. + +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. +D*/ + +/*F*/ +int get_PWM_range(int pi, unsigned user_gpio); +/*D +Get the range of PWM values being used on the gpio. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. +. . + +Returns the dutycycle range used for the gpio if OK, +otherwise PI_BAD_USER_GPIO. + +If a hardware clock or hardware PWM is active on the gpio the +reported range will be 1000000 (1M). +D*/ + +/*F*/ +int get_PWM_real_range(int pi, unsigned user_gpio); +/*D +Get the real underlying range of PWM values being used on the gpio. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. +. . + +Returns the real range used for the gpio if OK, +otherwise PI_BAD_USER_GPIO. + +If a hardware clock is active on the gpio the reported +real range will be 1000000 (1M). + +If hardware PWM is active on the gpio the reported real range +will be approximately 250M divided by the set PWM frequency. + +D*/ + +/*F*/ +int set_PWM_frequency(int pi, unsigned user_gpio, unsigned frequency); +/*D +Set the frequency (in Hz) of the PWM to be used on the gpio. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. +frequency: 0- (Hz). +. . + +Returns the numerically closest frequency if OK, otherwise +PI_BAD_USER_GPIO or PI_NOT_PERMITTED. + +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 +. . +D*/ + +/*F*/ +int get_PWM_frequency(int pi, unsigned user_gpio); +/*D +Get the frequency of PWM being used on the gpio. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. +. . + +For normal PWM the frequency will be that defined for the gpio by +[*set_PWM_frequency*]. + +If a hardware clock is active on the gpio the reported frequency +will be that set by [*hardware_clock*]. + +If hardware PWM is active on the gpio the reported frequency +will be that set by [*hardware_PWM*]. + +Returns the frequency (in hertz) used for the gpio if OK, +otherwise PI_BAD_USER_GPIO. +D*/ + +/*F*/ +int set_servo_pulsewidth(int pi, unsigned user_gpio, unsigned pulsewidth); +/*D +Start (500-2500) or stop (0) servo pulses on the gpio. + +. . + pi: 0- (as returned by [*pigpio_start*]). + user_gpio: 0-31. +pulsewidth: 0 (off), 500 (anti-clockwise) - 2500 (clockwise). +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_PULSEWIDTH or +PI_NOT_PERMITTED. + +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 pulsewidth. + +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. +D*/ + +/*F*/ +int get_servo_pulsewidth(int pi, unsigned user_gpio); +/*D +Return the servo pulsewidth in use on a gpio. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO or PI_NOT_SERVO_GPIO. +D*/ + +/*F*/ +int notify_open(int pi); +/*D +Get a free notification handle. + +. . +pi: 0- (as returned by [*pigpio_start*]). +. . + +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. +D*/ + +/*F*/ +int notify_begin(int pi, unsigned handle, uint32_t bits); +/*D +Start notifications on a previously opened handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: 0-31 (as returned by [*notify_open*]) + bits: a mask indicating the gpios to be notified. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE. + +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 +. . +D*/ + +/*F*/ +int notify_pause(int pi, unsigned handle); +/*D +Pause notifications on a previously opened handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: 0-31 (as returned by [*notify_open*]) +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE. + +Notifications for the handle are suspended until +[*notify_begin*] is called again. +D*/ + +/*F*/ +int notify_close(int pi, unsigned handle); +/*D +Stop notifications on a previously opened handle and +release the handle for reuse. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: 0-31 (as returned by [*notify_open*]) +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE. +D*/ + +/*F*/ +int set_watchdog(int pi, unsigned user_gpio, unsigned timeout); +/*D +Sets a watchdog for a gpio. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. + timeout: 0-60000. +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO +or PI_BAD_WDOG_TIMEOUT. + +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. +D*/ + +/*F*/ +int set_glitch_filter(int pi, unsigned user_gpio, unsigned steady); +/*D +Sets a glitch filter on a gpio. + +Level changes on the gpio are not reported unless the level +has been stable for at least [*steady*] microseconds. The +level is then reported. Level changes of less than [*steady*] +microseconds are ignored. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31 + steady: 0-300000 +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER. + +Note, each (stable) edge will be timestamped [*steady*] microseconds +after it was first detected. +D*/ + +/*F*/ +int set_noise_filter( + int pi, unsigned user_gpio, unsigned steady, unsigned active); +/*D +Sets a noise filter on a gpio. + +Level changes on the gpio are ignored until a level which has +been stable for [*steady*] microseconds is detected. Level changes +on the gpio are then reported for [*active*] microseconds after +which the process repeats. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31 + steady: 0-300000 + active: 0-1000000 +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER. + +Note, level changes before and after the active period may +be reported. Your software must be designed to cope with +such reports. +D*/ + +/*F*/ +uint32_t read_bank_1(int pi); +/*D +Read the levels of the bank 1 gpios (gpios 0-31). + +. . +pi: 0- (as returned by [*pigpio_start*]). +. . + +The returned 32 bit integer has a bit set if the corresponding +gpio is logic 1. Gpio n has bit value (1<=0, as returned by [*wave_create*]. +. . + +Wave ids are allocated in order, 0, 1, 2, etc. + +Returns 0 if OK, otherwise PI_BAD_WAVE_ID. +D*/ + +/*F*/ +int wave_send_once(int pi, unsigned wave_id); +/*D +This function transmits the waveform with id wave_id. The waveform +is sent once. + +NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled. + +. . + pi: 0- (as returned by [*pigpio_start*]). +wave_id: >=0, as returned by [*wave_create*]. +. . + +Returns the number of DMA control blocks in the waveform if OK, +otherwise PI_BAD_WAVE_ID, or PI_BAD_WAVE_MODE. +D*/ + +/*F*/ +int wave_send_repeat(int pi, unsigned wave_id); +/*D +This function transmits the waveform with id wave_id. The waveform +cycles until cancelled (either by the sending of a new waveform or +by [*wave_tx_stop*]). + +NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled. + +. . + pi: 0- (as returned by [*pigpio_start*]). +wave_id: >=0, as returned by [*wave_create*]. +. . + +Returns the number of DMA control blocks in the waveform if OK, +otherwise PI_BAD_WAVE_ID, or PI_BAD_WAVE_MODE. +D*/ + +/*F*/ +int wave_chain(int pi, char *buf, unsigned bufSize); +/*D +This function transmits a chain of waveforms. + +NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled. + +The waves to be transmitted are specified by the contents of buf +which contains an ordered list of [*wave_id*]s and optional command +codes and related data. + +. . + pi: 0- (as returned by [*pigpio_start*]). + buf: pointer to the wave_ids and optional command codes +bufSize: the number of bytes in buf +. . + +Returns 0 if OK, otherwise PI_CHAIN_NESTING, PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD, PI_CHAIN_COUNTER, +PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG, or PI_BAD_WAVE_ID. + +Each wave is transmitted in the order specified. A wave may +occur multiple times per chain. + +A blocks of waves may be transmitted multiple times by using +the loop commands. The block is bracketed by loop start and +end commands. Loops may be nested. + +Delays between waves may be added with the delay command. + +The following command codes are supported: + +Name @ Cmd & Data @ Meaning +Loop Start @ 255 0 @ Identify start of a wave block +Loop Repeat @ 255 1 x y @ loop x + y*256 times +Delay @ 255 2 x y @ delay x + y*256 microseconds +Loop Forever @ 255 3 @ loop forever + +If present Loop Forever must be the last entry in the chain. + +The code is currently dimensioned to support a chain with roughly +600 entries and 20 loop counters. + +... +#include +#include + +#define WAVES 5 +#define GPIO 4 + +int main(int argc, char *argv[]) +{ + int i, pi, wid[WAVES]; + + pi = pigpio_start(0, 0); + if (pi<0) return -1; + + set_mode(pi, GPIO, PI_OUTPUT); + + for (i=0; i=0, as returned by [*store_script*]. + numPar: 0-10, the number of parameters. + param: an array of parameters. +. . + +The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID, or +PI_TOO_MANY_PARAM + +param is an array of up to 10 parameters which may be referenced in +the script as p0 to p9. +D*/ + +/*F*/ +int script_status(int pi, unsigned script_id, uint32_t *param); +/*D +This function returns the run status of a stored script as well +as the current values of parameters 0 to 9. + +. . + pi: 0- (as returned by [*pigpio_start*]). +script_id: >=0, as returned by [*store_script*]. + param: an array to hold the returned 10 parameters. +. . + +The function returns greater than or equal to 0 if OK, +otherwise PI_BAD_SCRIPT_ID. + +The run status may be + +. . +PI_SCRIPT_INITING +PI_SCRIPT_HALTED +PI_SCRIPT_RUNNING +PI_SCRIPT_WAITING +PI_SCRIPT_FAILED +. . + +The current value of script parameters 0 to 9 are returned in param. +D*/ + +/*F*/ +int stop_script(int pi, unsigned script_id); +/*D +This function stops a running script. + +. . + pi: 0- (as returned by [*pigpio_start*]). +script_id: >=0, as returned by [*store_script*]. +. . + +The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID. +D*/ + +/*F*/ +int delete_script(int pi, unsigned script_id); +/*D +This function deletes a stored script. + +. . + pi: 0- (as returned by [*pigpio_start*]). +script_id: >=0, as returned by [*store_script*]. +. . + +The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID. +D*/ + +/*F*/ +int bb_serial_read_open(int pi, unsigned user_gpio, unsigned baud, unsigned data_bits); +/*D +This function opens a gpio for bit bang reading of serial data. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. + baud: 50-250000 +data_bits: 1-32 +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, +or PI_GPIO_IN_USE. + +The serial data is returned in a cyclic buffer and is read using +bb_serial_read. + +It is the caller's responsibility to read data from the cyclic buffer +in a timely fashion. +D*/ + +/*F*/ +int bb_serial_read(int pi, unsigned user_gpio, void *buf, size_t bufSize); +/*D +This function copies up to bufSize bytes of data read from the +bit bang serial cyclic buffer to the buffer starting at buf. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31, previously opened with [*bb_serial_read_open*]. + buf: an array to receive the read bytes. + bufSize: 0- +. . + +Returns the number of bytes copied if OK, otherwise PI_BAD_USER_GPIO +or PI_NOT_SERIAL_GPIO. + +The bytes returned for each character depend upon the number of +data bits [*data_bits*] specified in the [*bb_serial_read_open*] command. + +For [*data_bits*] 1-8 there will be one byte per character. +For [*data_bits*] 9-16 there will be two bytes per character. +For [*data_bits*] 17-32 there will be four bytes per character. +D*/ + +/*F*/ +int bb_serial_read_close(int pi, unsigned user_gpio); +/*D +This function closes a gpio for bit bang reading of serial data. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31, previously opened with [*bb_serial_read_open*]. +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SERIAL_GPIO. +D*/ + +/*F*/ +int bb_serial_invert(int pi, unsigned user_gpio, unsigned invert); +/*D +This function inverts serial logic for big bang serial reads. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31, previously opened with [*bb_serial_read_open*]. + invert: 0-1, 1 invert, 0 normal. +. . + +Returns 0 if OK, otherwise PI_NOT_SERIAL_GPIO or PI_BAD_SER_INVERT. +D*/ + +/*F*/ +int i2c_open(int pi, unsigned i2c_bus, unsigned i2c_addr, unsigned i2c_flags); +/*D +This returns a handle for the device at address i2c_addr on bus i2c_bus. + +. . + pi: 0- (as returned by [*pigpio_start*]). + i2c_bus: 0-1. + i2c_addr: 0x00-0x7F. +i2c_flags: 0. +. . + +No flags are currently defined. This parameter should be set to zero. + +Returns a handle (>=0) if OK, otherwise PI_BAD_I2C_BUS, PI_BAD_I2C_ADDR, +PI_BAD_FLAGS, PI_NO_HANDLE, or PI_I2C_OPEN_FAILED. + +For the SMBus commands the low level transactions are shown at the end +of the function description. The following abbreviations are used. + +. . +S (1 bit) : Start bit +P (1 bit) : Stop bit +Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. +A, NA (1 bit) : Accept and not accept bit. +Addr (7 bits): I2C 7 bit address. +i2c_reg (8 bits): A byte which often selects a register. +Data (8 bits): A data byte. +Count (8 bits): A byte defining the length of a block operation. + +[..]: Data sent by the device. +. . +D*/ + +/*F*/ +int i2c_close(int pi, unsigned handle); +/*D +This closes the I2C device associated with the handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*i2c_open*]. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE. +D*/ + +/*F*/ +int i2c_write_quick(int pi, unsigned handle, unsigned bit); +/*D +This sends a single bit (in the Rd/Wr bit) to the device associated +with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*i2c_open*]. + bit: 0-1, the value to write. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +Quick command. SMBus 2.0 5.5.1 +. . +S Addr bit [A] P +. . +D*/ + +/*F*/ +int i2c_write_byte(int pi, unsigned handle, unsigned bVal); +/*D +This sends a single byte to the device associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*i2c_open*]. + bVal: 0-0xFF, the value to write. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +Send byte. SMBus 2.0 5.5.2 +. . +S Addr Wr [A] bVal [A] P +. . +D*/ + +/*F*/ +int i2c_read_byte(int pi, unsigned handle); +/*D +This reads a single byte from the device associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*i2c_open*]. +. . + +Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE, +or PI_I2C_READ_FAILED. + +Receive byte. SMBus 2.0 5.5.3 +. . +S Addr Rd [A] [Data] NA P +. . +D*/ + +/*F*/ +int i2c_write_byte_data( + int pi, unsigned handle, unsigned i2c_reg, unsigned bVal); +/*D +This writes a single byte to the specified register of the device +associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). + handle: >=0, as returned by a call to [*i2c_open*]. +i2c_reg: 0-255, the register to write. + bVal: 0-0xFF, the value to write. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +Write byte. SMBus 2.0 5.5.4 +. . +S Addr Wr [A] i2c_reg [A] bVal [A] P +. . +D*/ + +/*F*/ +int i2c_write_word_data( + int pi, unsigned handle, unsigned i2c_reg, unsigned wVal); +/*D +This writes a single 16 bit word to the specified register of the device +associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). + handle: >=0, as returned by a call to [*i2c_open*]. +i2c_reg: 0-255, the register to write. + wVal: 0-0xFFFF, the value to write. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +Write word. SMBus 2.0 5.5.4 +. . +S Addr Wr [A] i2c_reg [A] wval_Low [A] wVal_High [A] P +. . +D*/ + +/*F*/ +int i2c_read_byte_data(int pi, unsigned handle, unsigned i2c_reg); +/*D +This reads a single byte from the specified register of the device +associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). + handle: >=0, as returned by a call to [*i2c_open*]. +i2c_reg: 0-255, the register to read. +. . + +Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +Read byte. SMBus 2.0 5.5.5 +. . +S Addr Wr [A] i2c_reg [A] S Addr Rd [A] [Data] NA P +. . +D*/ + +/*F*/ +int i2c_read_word_data(int pi, unsigned handle, unsigned i2c_reg); +/*D +This reads a single 16 bit word from the specified register of the device +associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). + handle: >=0, as returned by a call to [*i2c_open*]. +i2c_reg: 0-255, the register to read. +. . + +Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +Read word. SMBus 2.0 5.5.5 +. . +S Addr Wr [A] i2c_reg [A] + S Addr Rd [A] [DataLow] A [DataHigh] NA P +. . +D*/ + +/*F*/ +int i2c_process_call(int pi, unsigned handle, unsigned i2c_reg, unsigned wVal); +/*D +This writes 16 bits of data to the specified register of the device +associated with handle and and reads 16 bits of data in return. + +. . + pi: 0- (as returned by [*pigpio_start*]). + handle: >=0, as returned by a call to [*i2c_open*]. +i2c_reg: 0-255, the register to write/read. + wVal: 0-0xFFFF, the value to write. +. . + +Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +Process call. SMBus 2.0 5.5.6 +. . +S Addr Wr [A] i2c_reg [A] wVal_Low [A] wVal_High [A] + S Addr Rd [A] [DataLow] A [DataHigh] NA P +. . +D*/ + +/*F*/ +int i2c_write_block_data( + int pi, unsigned handle, unsigned i2c_reg, char *buf, unsigned count); +/*D +This writes up to 32 bytes to the specified register of the device +associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). + handle: >=0, as returned by a call to [*i2c_open*]. +i2c_reg: 0-255, the register to write. + buf: an array with the data to send. + count: 1-32, the number of bytes to write. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +Block write. SMBus 2.0 5.5.7 +. . +S Addr Wr [A] i2c_reg [A] count [A] buf0 [A] buf1 [A] ... + [A] bufn [A] P +. . +D*/ + +/*F*/ +int i2c_read_block_data(int pi, unsigned handle, unsigned i2c_reg, char *buf); +/*D +This reads a block of up to 32 bytes from the specified register of +the device associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). + handle: >=0, as returned by a call to [*i2c_open*]. +i2c_reg: 0-255, the register to read. + buf: an array to receive the read data. +. . + +The amount of returned data is set by the device. + +Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +Block read. SMBus 2.0 5.5.7 +. . +S Addr Wr [A] i2c_reg [A] + S Addr Rd [A] [Count] A [buf0] A [buf1] A ... A [bufn] NA P +. . +D*/ + +/*F*/ +int i2c_block_process_call( + int pi, unsigned handle, unsigned i2c_reg, char *buf, unsigned count); +/*D +This writes data bytes to the specified register of the device +associated with handle and reads a device specified number +of bytes of data in return. + +. . + pi: 0- (as returned by [*pigpio_start*]). + handle: >=0, as returned by a call to [*i2c_open*]. +i2c_reg: 0-255, the register to write/read. + buf: an array with the data to send and to receive the read data. + count: 1-32, the number of bytes to write. +. . + + +Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +The smbus 2.0 documentation states that a minimum of 1 byte may be +sent and a minimum of 1 byte may be received. The total number of +bytes sent/received must be 32 or less. + +Block write-block read. SMBus 2.0 5.5.8 +. . +S Addr Wr [A] i2c_reg [A] count [A] buf0 [A] ... + S Addr Rd [A] [Count] A [Data] ... A P +. . +D*/ + +/*F*/ +int i2c_read_i2c_block_data( + int pi, unsigned handle, unsigned i2c_reg, char *buf, unsigned count); +/*D +This reads count bytes from the specified register of the device +associated with handle . The count may be 1-32. + +. . + pi: 0- (as returned by [*pigpio_start*]). + handle: >=0, as returned by a call to [*i2c_open*]. +i2c_reg: 0-255, the register to read. + buf: an array to receive the read data. + count: 1-32, the number of bytes to read. +. . + +Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +. . +S Addr Wr [A] i2c_reg [A] + S Addr Rd [A] [buf0] A [buf1] A ... A [bufn] NA P +. . +D*/ + + +/*F*/ +int i2c_write_i2c_block_data( + int pi, unsigned handle, unsigned i2c_reg, char *buf, unsigned count); +/*D +This writes 1 to 32 bytes to the specified register of the device +associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). + handle: >=0, as returned by a call to [*i2c_open*]. +i2c_reg: 0-255, the register to write. + buf: the data to write. + count: 1-32, the number of bytes to write. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +. . +S Addr Wr [A] i2c_reg [A] buf0 [A] buf1 [A] ... [A] bufn [A] P +. . +D*/ + +/*F*/ +int i2c_read_device(int pi, unsigned handle, char *buf, unsigned count); +/*D +This reads count bytes from the raw device into buf. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*i2c_open*]. + buf: an array to receive the read data bytes. + count: >0, the number of bytes to read. +. . + +Returns count (>0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_READ_FAILED. + +. . +S Addr Rd [A] [buf0] A [buf1] A ... A [bufn] NA P +. . +D*/ + +/*F*/ +int i2c_write_device(int pi, unsigned handle, char *buf, unsigned count); +/*D +This writes count bytes from buf to the raw device. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*i2c_open*]. + buf: an array containing the data bytes to write. + count: >0, the number of bytes to write. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_I2C_WRITE_FAILED. + +. . +S Addr Wr [A] buf0 [A] buf1 [A] ... [A] bufn [A] P +. . +D*/ + +/*F*/ +int i2c_zip( + int pi, + unsigned handle, + char *inBuf, + unsigned inLen, + char *outBuf, + unsigned outLen); +/*D +This function executes a sequence of I2C operations. The +operations to be performed are specified by the contents of inBuf +which contains the concatenated command codes and associated data. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*i2cOpen*] + inBuf: pointer to the concatenated I2C commands, see below + inLen: size of command buffer +outBuf: pointer to buffer to hold returned data +outLen: size of output buffer +. . + +Returns >= 0 if OK (the number of bytes read), otherwise +PI_BAD_HANDLE, PI_BAD_POINTER, PI_BAD_I2C_CMD, PI_BAD_I2C_RLEN. +PI_BAD_I2C_WLEN, or PI_BAD_I2C_SEG. + +The following command codes are supported: + +Name @ Cmd & Data @ Meaning +End @ 0 @ No more commands +Escape @ 1 @ Next P is two bytes +On @ 2 @ Switch combined flag on +Off @ 3 @ Switch combined flag off +Address @ 4 P @ Set I2C address to P +Flags @ 5 lsb msb @ Set I2C flags to lsb + (msb << 8) +Read @ 6 P @ Read P bytes of data +Write @ 7 P ... @ Write P bytes of data + +The address, read, and write commands take a parameter P. +Normally P is one byte (0-255). If the command is preceded by +the Escape command then P is two bytes (0-65535, least significant +byte first). + +The address defaults to that associated with the handle. +The flags default to 0. The address and flags maintain their +previous value until updated. + +The returned I2C data is stored in consecutive locations of outBuf. + +... +Set address 0x53, write 0x32, read 6 bytes +Set address 0x1E, write 0x03, read 6 bytes +Set address 0x68, write 0x1B, read 8 bytes +End + +0x04 0x53 0x07 0x01 0x32 0x06 0x06 +0x04 0x1E 0x07 0x01 0x03 0x06 0x06 +0x04 0x68 0x07 0x01 0x1B 0x06 0x08 +0x00 +... + +D*/ + +/*F*/ +int bb_i2c_open(int pi, unsigned SDA, unsigned SCL, unsigned baud); +/*D +This function selects a pair of gpios for bit banging I2C at a +specified baud rate. + +Bit banging I2C allows for certain operations which are not possible +with the standard I2C driver. + +o baud rates as low as 50 +o repeated starts +o clock stretching +o I2C on any pair of spare gpios + +. . + pi: 0- (as returned by [*pigpio_start*]). + SDA: 0-31 + SCL: 0-31 +baud: 50-500000 +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_I2C_BAUD, or +PI_GPIO_IN_USE. + +NOTE: + +The gpios used for SDA and SCL must have pull-ups to 3V3 connected. As +a guide the hardware pull-ups on pins 3 and 5 are 1k8 in value. +D*/ + +/*F*/ +int bb_i2c_close(int pi, unsigned SDA); +/*D +This function stops bit banging I2C on a pair of gpios previously +opened with [*bb_i2c_open*]. + +. . + pi: 0- (as returned by [*pigpio_start*]). +SDA: 0-31, the SDA gpio used in a prior call to [*bb_i2c_open*] +. . + +Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_I2C_GPIO. +D*/ + +/*F*/ +int bb_i2c_zip( + int pi, + unsigned SDA, + char *inBuf, + unsigned inLen, + char *outBuf, + unsigned outLen); +/*D +This function executes a sequence of bit banged I2C operations. The +operations to be performed are specified by the contents of inBuf +which contains the concatenated command codes and associated data. + +. . + pi: 0- (as returned by [*pigpio_start*]). + SDA: 0-31 (as used in a prior call to [*bb_i2c_open*]) + inBuf: pointer to the concatenated I2C commands, see below + inLen: size of command buffer +outBuf: pointer to buffer to hold returned data +outLen: size of output buffer +. . + +Returns >= 0 if OK (the number of bytes read), otherwise +PI_BAD_USER_GPIO, PI_NOT_I2C_GPIO, PI_BAD_POINTER, +PI_BAD_I2C_CMD, PI_BAD_I2C_RLEN, PI_BAD_I2C_WLEN, +PI_I2C_READ_FAILED, or PI_I2C_WRITE_FAILED. + +The following command codes are supported: + +Name @ Cmd & Data @ Meaning +End @ 0 @ No more commands +Escape @ 1 @ Next P is two bytes +Start @ 2 @ Start condition +Stop @ 3 @ Stop condition +Address @ 4 P @ Set I2C address to P +Flags @ 5 lsb msb @ Set I2C flags to lsb + (msb << 8) +Read @ 6 P @ Read P bytes of data +Write @ 7 P ... @ Write P bytes of data + +The address, read, and write commands take a parameter P. +Normally P is one byte (0-255). If the command is preceded by +the Escape command then P is two bytes (0-65535, least significant +byte first). + +The address and flags default to 0. The address and flags maintain +their previous value until updated. + +No flags are currently defined. + +The returned I2C data is stored in consecutive locations of outBuf. + +... +Set address 0x53 +start, write 0x32, (re)start, read 6 bytes, stop +Set address 0x1E +start, write 0x03, (re)start, read 6 bytes, stop +Set address 0x68 +start, write 0x1B, (re)start, read 8 bytes, stop +End + +0x04 0x53 +0x02 0x07 0x01 0x32 0x02 0x06 0x06 0x03 + +0x04 0x1E +0x02 0x07 0x01 0x03 0x02 0x06 0x06 0x03 + +0x04 0x68 +0x02 0x07 0x01 0x1B 0x02 0x06 0x08 0x03 + +0x00 +... +D*/ + +/*F*/ +int spi_open(int pi, unsigned spi_channel, unsigned baud, unsigned spi_flags); +/*D +This function returns a handle for the SPI device on channel. +Data will be transferred at baud bits per second. The flags may +be used to modify the default behaviour of 4-wire operation, mode 0, +active low chip select. + +An auxiliary SPI device is available on the A+/B+/Pi2 and may be +selected by setting the A bit in the flags. The auxiliary +device has 3 chip selects and a selectable word size in bits. + +. . + pi: 0- (as returned by [*pigpio_start*]). +spi_channel: 0-1 (0-2 for A+/B+/Pi2 auxiliary device). + baud: 32K-125M (values above 30M are unlikely to work). + spi_flags: see below. +. . + +Returns a handle (>=0) if OK, otherwise PI_BAD_SPI_CHANNEL, +PI_BAD_SPI_SPEED, PI_BAD_FLAGS, PI_NO_AUX_SPI, or PI_SPI_OPEN_FAILED. + +spi_flags consists of the least significant 22 bits. + +. . +21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + b b b b b b R T n n n n W A u2 u1 u0 p2 p1 p0 m m +. . + +mm defines the SPI mode. + +Warning: modes 1 and 3 do not appear to work on the auxiliary device. + +. . +Mode POL PHA + 0 0 0 + 1 0 1 + 2 1 0 + 3 1 1 +. . + +px is 0 if CEx is active low (default) and 1 for active high. + +ux is 0 if the CEx gpio is reserved for SPI (default) and 1 otherwise. + +A is 0 for the standard SPI device, 1 for the auxiliary SPI. The +auxiliary device is only present on the A+/B+/Pi2. + +W is 0 if the device is not 3-wire, 1 if the device is 3-wire. Standard +SPI device only. + +nnnn defines the number of bytes (0-15) to write before switching +the MOSI line to MISO to read data. This field is ignored +if W is not set. Standard SPI device only. + +T is 1 if the least significant bit is transmitted on MOSI first, the +default (0) shifts the most significant bit out first. Auxiliary SPI +device only. + +R is 1 if the least significant bit is received on MISO first, the +default (0) receives the most significant bit first. Auxiliary SPI +device only. + +bbbbbb defines the word size in bits (0-32). The default (0) +sets 8 bits per word. Auxiliary SPI device only. + +The other bits in flags should be set to zero. +D*/ + +/*F*/ +int spi_close(int pi, unsigned handle); +/*D +This functions closes the SPI device identified by the handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*spi_open*]. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE. +D*/ + +/*F*/ +int spi_read(int pi, unsigned handle, char *buf, unsigned count); +/*D +This function reads count bytes of data from the SPI +device associated with the handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*spi_open*]. + buf: an array to receive the read data bytes. + count: the number of bytes to read. +. . + +Returns the number of bytes transferred if OK, otherwise +PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED. +D*/ + +/*F*/ +int spi_write(int pi, unsigned handle, char *buf, unsigned count); +/*D +This function writes count bytes of data from buf to the SPI +device associated with the handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*spi_open*]. + buf: the data bytes to write. + count: the number of bytes to write. +. . + +Returns the number of bytes transferred if OK, otherwise +PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED. +D*/ + +/*F*/ +int spi_xfer( + int pi, unsigned handle, char *txBuf, char *rxBuf, unsigned count); +/*D +This function transfers count bytes of data from txBuf to the SPI +device associated with the handle. Simultaneously count bytes of +data are read from the device and placed in rxBuf. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*spi_open*]. + txBuf: the data bytes to write. + rxBuf: the received data bytes. + count: the number of bytes to transfer. +. . + +Returns the number of bytes transferred if OK, otherwise +PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED. +D*/ + +/*F*/ +int serial_open(int pi, char *ser_tty, unsigned baud, unsigned ser_flags); +/*D +This function opens a serial device at a specified baud rate +with specified flags. + +. . + pi: 0- (as returned by [*pigpio_start*]). + ser_tty: the serial device to open, /dev/tty*. + baud: the baud rate in bits per second, see below. +ser_flags: 0. +. . + +Returns a handle (>=0) if OK, otherwise PI_NO_HANDLE, or +PI_SER_OPEN_FAILED. + +The baud rate must be one of 50, 75, 110, 134, 150, +200, 300, 600, 1200, 1800, 2400, 4800, 9500, 19200, +38400, 57600, 115200, or 230400. + +No flags are currently defined. This parameter should be set to zero. +D*/ + +/*F*/ +int serial_close(int pi, unsigned handle); +/*D +This function closes the serial device associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*serial_open*]. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE. +D*/ + +/*F*/ +int serial_write_byte(int pi, unsigned handle, unsigned bVal); +/*D +This function writes bVal to the serial port associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*serial_open*]. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_SER_WRITE_FAILED. +D*/ + +/*F*/ +int serial_read_byte(int pi, unsigned handle); +/*D +This function reads a byte from the serial port associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*serial_open*]. +. . + +Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE, +PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED. +D*/ + +/*F*/ +int serial_write(int pi, unsigned handle, char *buf, unsigned count); +/*D +This function writes count bytes from buf to the the serial port +associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*serial_open*]. + buf: the array of bytes to write. + count: the number of bytes to write. +. . + +Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or +PI_SER_WRITE_FAILED. +D*/ + +/*F*/ +int serial_read(int pi, unsigned handle, char *buf, unsigned count); +/*D +This function reads up to count bytes from the the serial port +associated with handle and writes them to buf. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*serial_open*]. + buf: an array to receive the read data. + count: the maximum number of bytes to read. +. . + +Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE, +PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED. +D*/ + +/*F*/ +int serial_data_available(int pi, unsigned handle); +/*D +Returns the number of bytes available to be read from the +device associated with handle. + +. . + pi: 0- (as returned by [*pigpio_start*]). +handle: >=0, as returned by a call to [*serial_open*]. +. . + +Returns the number of bytes of data available (>=0) if OK, +otherwise PI_BAD_HANDLE. +D*/ + +/*F*/ +int custom_1(int pi, unsigned arg1, unsigned arg2, char *argx, unsigned argc); +/*D +This function is available for user customisation. + +It returns a single integer value. + +. . + pi: 0- (as returned by [*pigpio_start*]). +arg1: >=0 +arg2: >=0 +argx: extra (byte) arguments +argc: number of extra arguments +. . + +Returns >= 0 if OK, less than 0 indicates a user defined error. +D*/ + + +/*F*/ +int custom_2(int pi, unsigned arg1, char *argx, unsigned argc, + char *retBuf, unsigned retMax); +/*D +This function is available for user customisation. + +It differs from custom_1 in that it returns an array of bytes +rather than just an integer. + +The return value is an integer indicating the number of returned bytes. +. . + pi: 0- (as returned by [*pigpio_start*]). + arg1: >=0 + argc: extra (byte) arguments + count: number of extra arguments +retBuf: buffer for returned data +retMax: maximum number of bytes to return +. . + +Returns >= 0 if OK, less than 0 indicates a user defined error. + +Note, the number of returned bytes will be retMax or less. +D*/ + + +/*F*/ +int callback(int pi, unsigned user_gpio, unsigned edge, CBFunc_t f); +/*D +This function initialises a new callback. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. + edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE. + f: the callback function. +. . + +The function returns a callback id if OK, otherwise pigif_bad_malloc, +pigif_duplicate_callback, or pigif_bad_callback. + +The callback is called with the gpio, edge, and tick, whenever the +gpio has the identified edge. +D*/ + +/*F*/ +int callback_ex + (int pi, unsigned user_gpio, unsigned edge, CBFuncEx_t f, void *userdata); +/*D +This function initialises a new callback. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. + edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE. + f: the callback function. + userdata: a pointer to arbitrary user data. +. . + +The function returns a callback id if OK, otherwise pigif_bad_malloc, +pigif_duplicate_callback, or pigif_bad_callback. + +The callback is called with the gpio, edge, tick, and user, whenever +the gpio has the identified edge. +D*/ + +/*F*/ +int callback_cancel(unsigned callback_id); +/*D +This function cancels a callback identified by its id. + +. . +callback_id: >=0, as returned by a call to [*callback*] or [*callback_ex*]. +. . + +The function returns 0 if OK, otherwise pigif_callback_not_found. +D*/ + +/*F*/ +int wait_for_edge(int pi, unsigned user_gpio, unsigned edge, double timeout); +/*D +This function waits for edge on the gpio for up to timeout +seconds. + +. . + pi: 0- (as returned by [*pigpio_start*]). +user_gpio: 0-31. + edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE. + timeout: >=0. +. . + +The function returns 1 if the edge occurred, otherwise 0. + +The function returns when the edge occurs or after the timeout. +D*/ + +/*PARAMS + +active :: 0-1000000 + +The number of microseconds level changes are reported for once +a noise filter has been triggered (by [*steady*] microseconds of +a stable level). + +*addrStr:: +A string specifying the host or IP address of the Pi running +the pigpio daemon. It may be NULL in which case localhost +is used unless overridden by the PIGPIO_ADDR environment +variable. + +arg1:: +An unsigned argument passed to a user customised function. Its +meaning is defined by the customiser. + +arg2:: +An unsigned argument passed to a user customised function. Its +meaning is defined by the customiser. + +argc:: +The count of bytes passed to a user customised function. + +*argx:: +A pointer to an array of bytes passed to a user customised function. +Its meaning and content is defined by the customiser. + +baud:: +The speed of serial communication (I2C, SPI, serial link, waves) in +bits per second. + +bit:: +A value of 0 or 1. + +bits:: +A value used to select gpios. If bit n of bits is set then gpio n is +selected. + +A convenient way to set bit n is to or in (1<=0, as returned by a call to [*callback*] or [*callback_ex*]. This is +passed to [*callback_cancel*] to cancel the callback. + +CBFunc_t:: +. . +typedef void (*CBFunc_t) + (unsigned user_gpio, unsigned level, uint32_t tick); +. . + +CBFuncEx_t:: +. . +typedef void (*CBFuncEx_t) + (unsigned user_gpio, unsigned level, uint32_t tick, void * user); +. . + +char:: +A single character, an 8 bit quantity able to store 0-255. + +clkfreq::4689-250000000 (250M) +The hardware clock frequency. + +count:: +The number of bytes to be transferred in an I2C, SPI, or Serial +command. + +data_bits::1-32 +The number of data bits in each character of serial data. + +. . +#define PI_MIN_WAVE_DATABITS 1 +#define PI_MAX_WAVE_DATABITS 32 +. . + +double:: +A floating point number. + +dutycycle::0-range +A number representing the ratio of on time to off time for PWM. + +The number may vary between 0 and range (default 255) where +0 is off and range is fully on. + +edge:: +Used to identify a gpio level transition of interest. A rising edge is +a level change from 0 to 1. A falling edge is a level change from 1 to 0. + +. . +RISING_EDGE 0 +FALLING_EDGE 1 +EITHER_EDGE. 2 +. . + +errnum:: +A negative number indicating a function call failed and the nature +of the error. + +f:: +A function. + +frequency::0- +The number of times a gpio is swiched on and off per second. This +can be set per gpio and may be as little as 5Hz or as much as +40KHz. The gpio will be on for a proportion of the time as defined +by its dutycycle. + + +gpio:: +A Broadcom numbered gpio, in the range 0-53. + +There are 54 General Purpose Input Outputs (gpios) named gpio0 through +gpio53. + +They are split into two banks. Bank 1 consists of gpio0 through +gpio31. Bank 2 consists of gpio32 through gpio53. + +All the gpios which are safe for the user to read and write are in +bank 1. Not all gpios in bank 1 are safe though. Type 1 boards +have 17 safe gpios. Type 2 boards have 21. Type 3 boards have 26. + +See [*get_hardware_revision*]. + +The user gpios are marked with an X in the following table. + +. . + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +Type 1 X X - - X - - X X X X X - - X X +Type 2 - - X X X - - X X X X X - - X X +Type 3 X X X X X X X X X X X X X X + + 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 +Type 1 - X X - - X X X X X - - - - - - +Type 2 - X X - - - X X X X - X X X X X +Type 3 X X X X X X X X X X X X - - - - +. . + +gpioPulse_t:: +. . +typedef struct +{ +uint32_t gpioOn; +uint32_t gpioOff; +uint32_t usDelay; +} gpioPulse_t; +. . + +gpioThreadFunc_t:: +. . +typedef void *(gpioThreadFunc_t) (void *); +. . + +handle::0- +A number referencing an object opened by one of [*i2c_open*], [*notify_open*], +[*serial_open*], and [*spi_open*]. + +i2c_addr:: +The address of a device on the I2C bus. + +i2c_bus::0-1 +An I2C bus, 0 or 1. + +i2c_flags::0 +Flags which modify an I2C open command. None are currently defined. + +i2c_reg:: 0-255 +A register of an I2C device. + +*inBuf:: +A buffer used to pass data to a function. + +inLen:: +The number of bytes of data in a buffer. + +int:: +A whole number, negative or positive. + +invert:: +A flag used to set normal or inverted bit bang serial data level logic. + +level:: +The level of a gpio. Low or High. + +. . +PI_OFF 0 +PI_ON 1 + +PI_CLEAR 0 +PI_SET 1 + +PI_LOW 0 +PI_HIGH 1 +. . + +There is one exception. If a watchdog expires on a gpio the level will be +reported as PI_TIMEOUT. See [*set_watchdog*]. + +. . +PI_TIMEOUT 2 +. . + +mode::0-7 +The operational mode of a gpio, normally INPUT or OUTPUT. + +. . +PI_INPUT 0 +PI_OUTPUT 1 +PI_ALT0 4 +PI_ALT1 5 +PI_ALT2 6 +PI_ALT3 7 +PI_ALT4 3 +PI_ALT5 2 +. . + +numBytes:: +The number of bytes used to store characters in a string. Depending +on the number of bits per character there may be 1, 2, or 4 bytes +per character. + +numPar:: 0-10 +The number of parameters passed to a script. + +numPulses:: +The number of pulses to be added to a waveform. + +offset:: +The associated data starts this number of microseconds from the start of +the waveform. + +*outBuf:: +A buffer used to return data from a function. + +outLen:: +The size in bytes of an output buffer. + +*param:: +An array of script parameters. + +pi:: +An integer defining a connected Pi. The value is returned by +[*pigpio_start*] upon success. + +*portStr:: +A string specifying the port address used by the Pi running +the pigpio daemon. It may be NULL in which case "8888" +is used unless overridden by the PIGPIO_PORT environment +variable. + +*pth:: +A thread identifier, returned by [*start_thread*]. + + +pthread_t:: +A thread identifier. + +pud::0-2 +The setting of the pull up/down resistor for a gpio, which may be off, +pull-up, or pull-down. +. . +PI_PUD_OFF 0 +PI_PUD_DOWN 1 +PI_PUD_UP 2 +. . + +pulseLen:: +1-100, the length of a trigger pulse in microseconds. + +*pulses:: +An array of pulses to be added to a waveform. + +pulsewidth::0, 500-2500 +. . +PI_SERVO_OFF 0 +PI_MIN_SERVO_PULSEWIDTH 500 +PI_MAX_SERVO_PULSEWIDTH 2500 +. . + +PWMduty::0-1000000 (1M) +The hardware PWM dutycycle. + +. . +#define PI_HW_PWM_RANGE 1000000 +. . + +PWMfreq::1-125000000 (125M) +The hardware PWM frequency. + +. . +#define PI_HW_PWM_MIN_FREQ 1 +#define PI_HW_PWM_MAX_FREQ 125000000 +. . + +range::25-40000 +The permissible dutycycle values are 0-range. +. . +PI_MIN_DUTYCYCLE_RANGE 25 +PI_MAX_DUTYCYCLE_RANGE 40000 +. . + +*retBuf:: +A buffer to hold a number of bytes returned to a used customised function, + +retMax:: +The maximum number of bytes a user customised function should return. + + +*rxBuf:: +A pointer to a buffer to receive data. + +SCL:: +The user gpio to use for the clock when bit banging I2C. + +*script:: +A pointer to the text of a script. + +script_id:: +An id of a stored script as returned by [*store_script*]. + +SDA:: +The user gpio to use for data when bit banging I2C. + +seconds:: +The number of seconds. + +ser_flags:: +Flags which modify a serial open command. None are currently defined. + +*ser_tty:: +The name of a serial tty device, e.g. /dev/ttyAMA0, /dev/ttyUSB0, /dev/tty1. + +size_t:: +A standard type used to indicate the size of an object in bytes. + +spi_channel:: +A SPI channel, 0-2. + +spi_flags:: +See [*spi_open*]. + +steady :: 0-300000 + +The number of microseconds level changes must be stable for +before reporting the level changed ([*set_glitch_filter*]) or triggering +the active part of a noise filter ([*set_noise_filter*]). + +stop_bits::2-8 +The number of (half) stop bits to be used when adding serial data +to a waveform. + +. . +#define PI_MIN_WAVE_HALFSTOPBITS 2 +#define PI_MAX_WAVE_HALFSTOPBITS 8 +. . + +*str:: + An array of characters. + +thread_func:: +A function of type gpioThreadFunc_t used as the main function of a +thread. + +timeout:: +A gpio watchdog timeout in milliseconds. +. . +PI_MIN_WDOG_TIMEOUT 0 +PI_MAX_WDOG_TIMEOUT 60000 +. . + +*txBuf:: +An array of bytes to transmit. + +uint32_t::0-0-4,294,967,295 (Hex 0x0-0xFFFFFFFF) +A 32-bit unsigned value. + +unsigned:: +A whole number >= 0. + +user_gpio:: +0-31, a Broadcom numbered gpio. + +See [*gpio*]. + +*userdata:: + +A pointer to arbitrary user data. This may be used to identify the instance. + +You must ensure that the pointer is in scope at the time it is processed. If +it is a pointer to a global this is automatic. Do not pass the address of a +local variable. If you want to pass a transient object then use the +following technique. + +In the calling function: + +user_type *userdata; +user_type my_userdata; + +userdata = malloc(sizeof(user_type)); +*userdata = my_userdata; + +In the receiving function: + +user_type my_userdata = *(user_type*)userdata; + +free(userdata); + +void:: +Denoting no parameter is required + +wave_add_*:: +One of [*wave_add_new*], [*wave_add_generic*], [*wave_add_serial*]. + +wave_id:: +A number representing a waveform created by [*wave_create*]. + +wave_send_*:: +One of [*wave_send_once*], [*wave_send_repeat*]. + +wVal::0-65535 (Hex 0x0-0xFFFF, Octal 0-0177777) +A 16-bit word value. + +PARAMS*/ + +/*DEF_S pigpiod_if2 Error Codes*/ + +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, + pigif_unconnected_pi = -2011, + pigif_too_many_pis = -2012, +} pigifError_t; + +/*DEF_E*/ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/pigs.1 b/pigs.1 index a3706e6..12cad6b 100644 --- a/pigs.1 +++ b/pigs.1 @@ -2,7 +2,7 @@ ." Process this file with ." groff -man -Tascii foo.1 ." -.TH pigs 1 2012-2014 Linux "pigpio archive" +.TH pigs 1 2012-2015 Linux "pigpio archive" .SH NAME pigs - command line socket access to the pigpio daemon. @@ -4339,7 +4339,7 @@ the current gpio levels. .SH SEE ALSO -pigpiod(1), pig2vcd(1), pigpio(3), pigpiod_if(3) +pigpiod(1), pig2vcd(1), pigpio(3), pigpiod_if(3), pigpiod_if2(3) .SH AUTHOR joan@abyz.co.uk diff --git a/setup.py b/setup.py index a7df3a0..407cb8d 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from distutils.core import setup setup(name='pigpio', - version='1.23', + version='1.24', author='joan', author_email='joan@abyz.co.uk', maintainer='joan', diff --git a/x_pigpiod_if2.c b/x_pigpiod_if2.c new file mode 100644 index 0000000..732f772 --- /dev/null +++ b/x_pigpiod_if2.c @@ -0,0 +1,884 @@ +/* +gcc -o x_pigpiod_if2 x_pigpiod_if2.c -lpigpiod_if2 -lpthread +./x_pigpiod_if2 + +*** WARNING ************************************************ +* * +* All the tests make extensive use of gpio 4 (pin P1-7). * +* Ensure that either nothing or just a LED is connected to * +* gpio 4 before running any of the tests. * +* * +* Some tests are statistical in nature and so may on * +* occasion fail. Repeated failures on the same test or * +* many failures in a group of tests indicate a problem. * +************************************************************ +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "pigpiod_if2.h" + +#define GPIO 4 + +void CHECK(int t, int st, int got, int expect, int pc, char *desc) +{ + if ((got >= (((1E2-pc)*expect)/1E2)) && (got <= (((1E2+pc)*expect)/1E2))) + { + printf("TEST %2d.%-2d PASS (%s: %d)\n", t, st, desc, expect); + } + else + { + fprintf(stderr, + "TEST %2d.%-2d FAILED got %d (%s: %d)\n", + t, st, got, desc, expect); + } +} + +void t0(int pi) +{ + printf("Version.\n"); + + printf("pigpio version %d.\n", get_pigpio_version(pi)); + + printf("Hardware revision %d.\n", get_hardware_revision(pi)); +} + +void t1(int pi) +{ + int v; + + printf("Mode/PUD/read/write tests.\n"); + + set_mode(pi, GPIO, PI_INPUT); + v = get_mode(pi, GPIO); + CHECK(1, 1, v, 0, 0, "set mode, get mode"); + + set_pull_up_down(pi, GPIO, PI_PUD_UP); + v = gpio_read(pi, GPIO); + CHECK(1, 2, v, 1, 0, "set pull up down, read"); + + set_pull_up_down(pi, GPIO, PI_PUD_DOWN); + v = gpio_read(pi, GPIO); + CHECK(1, 3, v, 0, 0, "set pull up down, read"); + + gpio_write(pi, GPIO, PI_LOW); + v = get_mode(pi, GPIO); + CHECK(1, 4, v, 1, 0, "write, get mode"); + + v = gpio_read(pi, GPIO); + CHECK(1, 5, v, 0, 0, "read"); + + gpio_write(pi, GPIO, PI_HIGH); + v = gpio_read(pi, GPIO); + CHECK(1, 6, v, 1, 0, "write, read"); +} + +int t2_count=0; + +void t2cb(int pi, unsigned gpio, unsigned level, uint32_t tick) +{ + t2_count++; +} + +void t2(int pi) +{ + int dc, f, r, rr, oc, id; + + printf("PWM dutycycle/range/frequency tests.\n"); + + set_PWM_range(pi, GPIO, 255); + set_PWM_frequency(pi, GPIO, 0); + f = get_PWM_frequency(pi, GPIO); + CHECK(2, 1, f, 10, 0, "set PWM range, set/get PWM frequency"); + + id = callback(pi, GPIO, EITHER_EDGE, t2cb); + + set_PWM_dutycycle(pi, GPIO, 0); + dc = get_PWM_dutycycle(pi, GPIO); + CHECK(2, 2, dc, 0, 0, "get PWM dutycycle"); + + time_sleep(0.5); /* allow old notifications to flush */ + oc = t2_count; + time_sleep(2); + f = t2_count - oc; + CHECK(2, 3, f, 0, 0, "set PWM dutycycle, callback"); + + set_PWM_dutycycle(pi, GPIO, 128); + dc = get_PWM_dutycycle(pi, GPIO); + CHECK(2, 4, dc, 128, 0, "get PWM dutycycle"); + + oc = t2_count; + time_sleep(2); + f = t2_count - oc; + CHECK(2, 5, f, 40, 5, "set PWM dutycycle, callback"); + + set_PWM_frequency(pi, GPIO, 100); + f = get_PWM_frequency(pi, GPIO); + CHECK(2, 6, f, 100, 0, "set/get PWM frequency"); + + oc = t2_count; + time_sleep(2); + f = t2_count - oc; + CHECK(2, 7, f, 400, 1, "callback"); + + set_PWM_frequency(pi, GPIO, 1000); + f = get_PWM_frequency(pi, GPIO); + CHECK(2, 8, f, 1000, 0, "set/get PWM frequency"); + + oc = t2_count; + time_sleep(2); + f = t2_count - oc; + CHECK(2, 9, f, 4000, 1, "callback"); + + r = get_PWM_range(pi, GPIO); + CHECK(2, 10, r, 255, 0, "get PWM range"); + + rr = get_PWM_real_range(pi, GPIO); + CHECK(2, 11, rr, 200, 0, "get PWM real range"); + + set_PWM_range(pi, GPIO, 2000); + r = get_PWM_range(pi, GPIO); + CHECK(2, 12, r, 2000, 0, "set/get PWM range"); + + rr = get_PWM_real_range(pi, GPIO); + CHECK(2, 13, rr, 200, 0, "get PWM real range"); + + set_PWM_dutycycle(pi, GPIO, 0); + + callback_cancel(id); +} + +int t3_reset=1; +int t3_count=0; +uint32_t t3_tick=0; +float t3_on=0.0; +float t3_off=0.0; + +void t3cbf(int pi, unsigned gpio, unsigned level, uint32_t tick) +{ + uint32_t td; + +// printf("pi=%d g=%d l=%d t=%u\n", pi, gpio, level, tick); + if (t3_reset) + { + t3_count = 0; + t3_on = 0.0; + t3_off = 0.0; + t3_reset = 0; + } + else + { + td = tick - t3_tick; + + if (level == 0) t3_on += td; + else t3_off += td; + } + + t3_count ++; + t3_tick = tick; +} + +void t3(int pi) +{ + int pw[3]={500, 1500, 2500}; + int dc[4]={20, 40, 60, 80}; + + int f, rr, v; + float on, off; + + int t, id; + + printf("PWM/Servo pulse accuracy tests.\n"); + + id = callback(pi, GPIO, EITHER_EDGE, t3cbf); + + for (t=0; t<3; t++) + { + set_servo_pulsewidth(pi, GPIO, pw[t]); + v = get_servo_pulsewidth(pi, GPIO); + CHECK(3, t+t+1, v, pw[t], 0, "get servo pulsewidth"); + + time_sleep(1); + t3_reset = 1; + time_sleep(4); + on = t3_on; + off = t3_off; + CHECK(3, t+t+2, (1000.0*(on+off))/on, 20000000.0/pw[t], 1, + "set servo pulsewidth"); + } + + set_servo_pulsewidth(pi, GPIO, 0); + set_PWM_frequency(pi, GPIO, 1000); + f = get_PWM_frequency(pi, GPIO); + CHECK(3, 7, f, 1000, 0, "set/get PWM frequency"); + + rr = set_PWM_range(pi, GPIO, 100); + CHECK(3, 8, rr, 200, 0, "set PWM range"); + + for (t=0; t<4; t++) + { + set_PWM_dutycycle(pi, GPIO, dc[t]); + v = get_PWM_dutycycle(pi, GPIO); + CHECK(3, t+t+9, v, dc[t], 0, "get PWM dutycycle"); + + time_sleep(1); + t3_reset = 1; + time_sleep(2); + on = t3_on; + off = t3_off; + CHECK(3, t+t+10, (1000.0*on)/(on+off), 10.0*dc[t], 1, + "set PWM dutycycle"); + } + + set_PWM_dutycycle(pi, GPIO, 0); + + callback_cancel(id); +} + +void t4(int pi) +{ + int h, e, f, n, s, b, l, seq_ok, toggle_ok; + gpioReport_t r; + char p[32]; + + printf("Pipe notification tests.\n"); + + set_PWM_frequency(pi, GPIO, 0); + set_PWM_dutycycle(pi, GPIO, 0); + set_PWM_range(pi, GPIO, 100); + + h = notify_open(pi); + e = notify_begin(pi, h, (1<<4)); + CHECK(4, 1, e, 0, 0, "notify open/begin"); + + time_sleep(1); + + sprintf(p, "/dev/pigpio%d", h); + + f = open(p, O_RDONLY); + + set_PWM_dutycycle(pi, GPIO, 50); + time_sleep(4); + set_PWM_dutycycle(pi, GPIO, 0); + + e = notify_pause(pi, h); + CHECK(4, 2, e, 0, 0, "notify pause"); + + e = notify_close(pi, h); + CHECK(4, 3, e, 0, 0, "notify close"); + + n = 0; + s = 0; + l = 0; + seq_ok = 1; + toggle_ok = 1; + + while (1) + { + b = read(f, &r, 12); + if (b == 12) + { + if (s != r.seqno) seq_ok = 0; + + if (n) if (l != (r.level&(1<<4))) toggle_ok = 0; + + if (r.level&(1<<4)) l = 0; + else l = (1<<4); + + s++; + n++; + + // printf("%d %d %d %X\n", r.seqno, r.flags, r.tick, r.level); + } + else break; + } + close(f); + + CHECK(4, 4, seq_ok, 1, 0, "sequence numbers ok"); + + CHECK(4, 5, toggle_ok, 1, 0, "gpio toggled ok"); + + CHECK(4, 6, n, 80, 10, "number of notifications"); +} + +int t5_count = 0; + +void t5cbf(int pi, unsigned gpio, unsigned level, uint32_t tick) +{ + t5_count++; +} + +void t5(int pi) +{ + int BAUD=4800; + + char *TEXT= +"\n\ +Now is the winter of our discontent\n\ +Made glorious summer by this sun of York;\n\ +And all the clouds that lour'd upon our house\n\ +In the deep bosom of the ocean buried.\n\ +Now are our brows bound with victorious wreaths;\n\ +Our bruised arms hung up for monuments;\n\ +Our stern alarums changed to merry meetings,\n\ +Our dreadful marches to delightful measures.\n\ +Grim-visaged war hath smooth'd his wrinkled front;\n\ +And now, instead of mounting barded steeds\n\ +To fright the souls of fearful adversaries,\n\ +He capers nimbly in a lady's chamber\n\ +To the lascivious pleasing of a lute.\n\ +"; + + gpioPulse_t wf[] = + { + {1< 0) text[c] = 0; /* null terminate string */ + CHECK(5, 11, strcmp(TEXT, text), 0, 0, "wave tx busy, serial read"); + + e = bb_serial_read_close(pi, GPIO); + CHECK(5, 12, e, 0, 0, "serial read close"); + + c = wave_get_micros(pi); + CHECK(5, 13, c, 6158148, 0, "wave get micros"); + + c = wave_get_high_micros(pi); + if (c > 6158148) c = 6158148; + CHECK(5, 14, c, 6158148, 0, "wave get high micros"); + + c = wave_get_max_micros(pi); + CHECK(5, 15, c, 1800000000, 0, "wave get max micros"); + + c = wave_get_pulses(pi); + CHECK(5, 16, c, 3405, 0, "wave get pulses"); + + c = wave_get_high_pulses(pi); + CHECK(5, 17, c, 3405, 0, "wave get high pulses"); + + c = wave_get_max_pulses(pi); + CHECK(5, 18, c, 12000, 0, "wave get max pulses"); + + c = wave_get_cbs(pi); + CHECK(5, 19, c, 6810, 0, "wave get cbs"); + + c = wave_get_high_cbs(pi); + CHECK(5, 20, c, 6810, 0, "wave get high cbs"); + + c = wave_get_max_cbs(pi); + CHECK(5, 21, c, 25016, 0, "wave get max cbs"); + + callback_cancel(id); +} + +int t6_count=0; +int t6_on=0; +uint32_t t6_on_tick=0; + +void t6cbf(int pi, unsigned gpio, unsigned level, uint32_t tick) +{ + if (level == 1) + { + t6_on_tick = tick; + t6_count++; + } + else + { + if (t6_on_tick) t6_on += (tick - t6_on_tick); + } +} + +void t6(int pi) +{ + int tp, t, p, id; + + printf("Trigger tests.\n"); + + gpio_write(pi, GPIO, PI_LOW); + + tp = 0; + + id = callback(pi, GPIO, EITHER_EDGE, t6cbf); + + time_sleep(0.2); + + for (t=0; t<5; t++) + { + time_sleep(0.1); + p = 10 + (t*10); + tp += p; + gpio_trigger(pi, GPIO, p, 1); + } + + time_sleep(0.5); + + CHECK(6, 1, t6_count, 5, 0, "gpio trigger count"); + + CHECK(6, 2, t6_on, tp, 25, "gpio trigger pulse length"); + + callback_cancel(id); +} + +int t7_count=0; + +void t7cbf(int pi, unsigned gpio, unsigned level, uint32_t tick) +{ + if (level == PI_TIMEOUT) t7_count++; +} + +void t7(int pi) +{ + int c, oc, id; + + printf("Watchdog tests.\n"); + + /* type of edge shouldn't matter for watchdogs */ + id = callback(pi, GPIO, FALLING_EDGE, t7cbf); + + set_watchdog(pi, GPIO, 10); /* 10 ms, 100 per second */ + time_sleep(0.5); + oc = t7_count; + time_sleep(2); + c = t7_count - oc; + CHECK(7, 1, c, 200, 1, "set watchdog on count"); + + set_watchdog(pi, GPIO, 0); /* 0 switches watchdog off */ + time_sleep(0.5); + oc = t7_count; + time_sleep(2); + c = t7_count - oc; + CHECK(7, 2, c, 0, 1, "set watchdog off count"); + + callback_cancel(id); +} + +void t8(int pi) +{ + int v, t, i; + + printf("Bank read/write tests.\n"); + + gpio_write(pi, GPIO, 0); + v = read_bank_1(pi) & (1<= 0) text[b] = 0; + CHECK(10, 7, strcmp(TEXT, text), 0, 0, "serial read"); + + b = serial_read_byte(pi, h); + CHECK(10, 8, b, 0xAA, 0, "serial read byte"); + + b = serial_read_byte(pi, h); + CHECK(10, 9, b, 0x55, 0, "serial read byte"); + + b = serial_read_byte(pi, h); + CHECK(10, 10, b, 0x00, 0, "serial read byte"); + + b = serial_read_byte(pi, h); + CHECK(10, 11, b, 0xFF, 0, "serial read byte"); + + b = serial_data_available(pi, h); + CHECK(10, 12, b, 0, 0, "serial data availabe"); + + e = serial_close(pi, h); + CHECK(10, 13, e, 0, 0, "serial close"); +} + +void tb(int pi) +{ + int h, e, b, len; + char *exp; + char buf[128]; + + printf("SMBus / I2C tests."); + + /* this test requires an ADXL345 on I2C bus 1 addr 0x53 */ + + h = i2c_open(pi, 1, 0x53, 0); + CHECK(11, 1, h, 0, 0, "i2c open"); + + e = i2c_write_device(pi, h, "\x00", 1); /* move to known register */ + CHECK(11, 2, e, 0, 0, "i2c write device"); + + b = i2c_read_device(pi, h, buf, 1); + CHECK(11, 3, b, 1, 0, "i2c read device"); + CHECK(11, 4, buf[0], 0xE5, 0, "i2c read device"); + + b = i2c_read_byte(pi, h); + CHECK(11, 5, b, 0xE5, 0, "i2c read byte"); + + b = i2c_read_byte_data(pi, h, 0); + CHECK(11, 6, b, 0xE5, 0, "i2c read byte data"); + + b = i2c_read_byte_data(pi, h, 48); + CHECK(11, 7, b, 2, 0, "i2c read byte data"); + + exp = "\x1D[aBcDeFgHjKM]"; + len = strlen(exp); + + e = i2c_write_device(pi, h, exp, len); + CHECK(11, 8, e, 0, 0, "i2c write device"); + + e = i2c_write_device(pi, h, "\x1D", 1); + b = i2c_read_device(pi, h, buf, len-1); + CHECK(11, 9, b, len-1, 0, "i2c read device"); + CHECK(11, 10, strncmp(buf, exp+1, len-1), 0, 0, "i2c read device"); + + if (strncmp(buf, exp+1, len-1)) + printf("got [%.*s] expected [%.*s]\n", len-1, buf, len-1, exp+1); + + e = i2c_write_byte_data(pi, h, 0x1d, 0xAA); + CHECK(11, 11, e, 0, 0, "i2c write byte data"); + + b = i2c_read_byte_data(pi, h, 0x1d); + CHECK(11, 12, b, 0xAA, 0, "i2c read byte data"); + + e = i2c_write_byte_data(pi, h, 0x1d, 0x55); + CHECK(11, 13, e, 0, 0, "i2c write byte data"); + + b = i2c_read_byte_data(pi, h, 0x1d); + CHECK(11, 14, b, 0x55, 0, "i2c read byte data"); + + exp = "[1234567890#]"; + len = strlen(exp); + + e = i2c_write_block_data(pi, h, 0x1C, exp, len); + CHECK(11, 15, e, 0, 0, "i2c write block data"); + + e = i2c_write_device(pi, h, "\x1D", 1); + b = i2c_read_device(pi, h, buf, len); + CHECK(11, 16, b, len, 0, "i2c read device"); + CHECK(11, 17, strncmp(buf, exp, len), 0, 0, "i2c read device"); + + if (strncmp(buf, exp, len)) + printf("got [%.*s] expected [%.*s]\n", len, buf, len, exp); + + b = i2c_read_i2c_block_data(pi, h, 0x1D, buf, len); + CHECK(11, 18, b, len, 0, "i2c read i2c block data"); + CHECK(11, 19, strncmp(buf, exp, len), 0, 0, "i2c read i2c block data"); + + if (strncmp(buf, exp, len)) + printf("got [%.*s] expected [%.*s]\n", len, buf, len, exp); + + exp = "(-+=;:,<>!%)"; + len = strlen(exp); + + e = i2c_write_i2c_block_data(pi, h, 0x1D, exp, len); + CHECK(11, 20, e, 0, 0, "i2c write i2c block data"); + + b = i2c_read_i2c_block_data(pi, h, 0x1D, buf, len); + CHECK(11, 21, b, len, 0, "i2c read i2c block data"); + CHECK(11, 22, strncmp(buf, exp, len), 0, 0, "i2c read i2c block data"); + + if (strncmp(buf, exp, len)) + printf("got [%.*s] expected [%.*s]\n", len, buf, len, exp); + + e = i2c_close(pi, h); + CHECK(11, 23, e, 0, 0, "i2c close"); +} + +void tc(int pi) +{ + int h, x, b, e; + char buf[128]; + + printf("SPI tests."); + + /* this test requires a MCP3202 on SPI channel 1 */ + + h = spi_open(pi, 1, 50000, 0); + CHECK(12, 1, h, 0, 0, "spi open"); + + + for (x=0; x<5; x++) + { + sprintf(buf, "\x01\x80"); + b = spi_xfer(pi, h, buf, buf, 3); + CHECK(12, 2, b, 3, 0, "spi xfer"); + if (b == 3) + { + time_sleep(1.0); + printf("%d ", ((buf[1]&0x0F)*256)|buf[2]); + } + } + + e = spi_close(pi, h); + CHECK(12, 99, e, 0, 0, "spi close"); +} + + +int main(int argc, char *argv[]) +{ + int i, t, c, pi; + + char test[64]; + + if (argc > 1) + { + t = 0; + + for (i=0; i