V10
authorjoan <joan@abyz.me.uk>
Sun, 12 Jan 2014 21:31:59 +0000 (21:31 +0000)
committerjoan <joan@abyz.me.uk>
Sun, 12 Jan 2014 21:31:59 +0000 (21:31 +0000)
MakeRemote [new file with mode: 0644]
Makefile
README
command.c
demolib.c [deleted file]
pigpio.c
pigpio.h
pigpio.py
pigpiod_if.c [new file with mode: 0644]
pigpiod_if.h [new file with mode: 0644]
setup.py

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