V32-a
authorjoan <joan@abyz.co.uk>
Thu, 23 Apr 2015 07:58:59 +0000 (08:58 +0100)
committerjoan <joan@abyz.co.uk>
Thu, 23 Apr 2015 07:58:59 +0000 (08:58 +0100)
Makefile
command.c
pigpio.3
pigpio.c
pigpio.h
pigpio.py
pigs.c
setup.py

index 08856bd7b654bcd4622db9f295fad7eddca27065..2cfc4b813530725eedc91cf1dae26a38a87a2fdd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -52,7 +52,8 @@ install:      $(LIB)
        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
+       sudo python2 setup.py install
+       sudo python3 setup.py install
        sudo install -m 0755 -d              /usr/local/man/man1
        sudo install -m 0644 *.1             /usr/local/man/man1
        sudo install -m 0755 -d              /usr/local/man/man3
@@ -66,6 +67,12 @@ uninstall:
        sudo rm -f /usr/local/bin/pig2vcd
        sudo rm -f /usr/local/bin/pigpiod
        sudo rm -f /usr/local/bin/pigs
+       echo removing python2 files
+       sudo python2 setup.py install --record /tmp/pigpio >/dev/null
+       sudo xargs rm -f < /tmp/pigpio >/dev/null
+       echo removing python3 files
+       sudo python3 setup.py install --record /tmp/pigpio >/dev/null
+       sudo xargs rm -f < /tmp/pigpio >/dev/null
        sudo rm -f /usr/local/man/man1/pig*.1
        sudo rm -f /usr/local/man/man3/pig*.3
 
index 06fc9147515cd105f2226be38d48f49195b2518f..baa41ebc8c450a454575ded3384a9901d8924d5b 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 31+
+This version is for pigpio version 32+
 */
 
 #include <stdio.h>
@@ -45,6 +45,10 @@ cmdInfo_t cmdInfo[]=
    {PI_CMD_BC1,   "BC1",   111, 1}, // gpioWrite_Bits_0_31_Clear
    {PI_CMD_BC2,   "BC2",   111, 1}, // gpioWrite_Bits_32_53_Clear
 
+   {PI_CMD_BI2CC, "BI2CC", 112, 0}, // bbI2CClose
+   {PI_CMD_BI2CO, "BI2CO", 131, 0}, // bbI2COpen
+   {PI_CMD_BI2CX, "BI2CX", 193, 6}, // bbI2CXfer
+
    {PI_CMD_BR1,   "BR1",   101, 3}, // gpioRead_Bits_0_31
    {PI_CMD_BR2,   "BR2",   101, 3}, // gpioRead_Bits_32_53
 
@@ -86,6 +90,8 @@ cmdInfo_t cmdInfo[]=
    {PI_CMD_I2CWS, "I2CWS", 121, 0}, // i2cWriteByte
    {PI_CMD_I2CWW, "I2CWW", 131, 0}, // i2cWriteWordData
 
+   {PI_CMD_I2CX,  "I2CX",  131, 0}, // i2cXfer
+
    {PI_CMD_MICS,  "MICS",  112, 0}, // gpioDelay
    {PI_CMD_MILS,  "MILS",  112, 0}, // gpioDelay
 
@@ -243,23 +249,23 @@ HWVER            Get hardware version\n\
 I2CC h           Close I2C handle\n\
 I2CO ib id if    Open I2C bus and device with flags\n\
 \n\
-I2CPC h r wv     smb Process Call: exchange register with word\n\
-I2CPK h r bvs    smb Block Process Call: exchange data bytes with register\n\
+I2CPC h r wv     SMBus Process Call: exchange register with word\n\
+I2CPK h r bvs    SMBus Block Process Call: exchange data bytes with register\n\
 \n\
-I2CRB h r        smb Read Byte Data: read byte from register\n\
+I2CRB h r        SMBus Read Byte Data: read byte from register\n\
 I2CRD h num      i2c Read bytes\n\
-I2CRI h r num    smb Read I2C Block Data: read bytes from register\n\
-I2CRK h r        smb Read Block Data: read data from register\n\
-I2CRS h          smb Read Byte: read byte\n\
-I2CRW h r        smb Read Word Data: read word from register\n\
+I2CRI h r num    SMBus Read I2C Block Data: read bytes from register\n\
+I2CRK h r        SMBus Read Block Data: read data from register\n\
+I2CRS h          SMBus Read Byte: read byte\n\
+I2CRW h r        SMBus Read Word Data: read word from register\n\
 \n\
-I2CWB h r bv     smb Write Byte Data: write byte to register\n\
+I2CWB h r bv     SMBus Write Byte Data: write byte to register\n\
 I2CWD h bvs      i2c Write data\n\
-I2CWI h r bvs    smb Write I2C Block Data\n\
-I2CWK h r bvs    smb Write Block Data: write data to register\n\
-I2CWQ h bit      smb Write Quick: write bit\n\
-I2CWS h bv       smb Write Byte: write byte\n\
-I2CWW h r wv     smb Write Word Data: write word to register\n\
+I2CWI h r bvs    SMBus Write I2C Block Data\n\
+I2CWK h r bvs    SMBus Write Block Data: write data to register\n\
+I2CWQ h bit      SMBus Write Quick: write bit\n\
+I2CWS h bv       SMBus Write Byte: write byte\n\
+I2CWW h r wv     SMBus Write Word Data: write word to register\n\
 \n\
 M/MODES g m      Set gpio mode\n\
 MG/MODEG g       Get gpio mode\n\
@@ -428,7 +434,7 @@ static errInfo_t errInfo[]=
    {PI_BAD_WAVE_BAUD    , "baud rate not 50-250K(RX)/50-1M(TX)"},
    {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_NOT_SERIAL_GPIO  , "no bit bang 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"},
@@ -496,6 +502,8 @@ static errInfo_t errInfo[]=
    {PI_BAD_MALLOC_MODE  , "bad memory allocation mode"},
    {PI_TOO_MANY_PARTS   , "too many I2C transaction parts"},
    {PI_BAD_I2C_PART     , "a combined I2C transaction failed"},
+   {PI_BAD_SMBUS_CMD    , "SMBus command not supported by driver"},
+   {PI_NOT_I2C_GPIO     , "no bit bang I2C in progress on gpio"},
 
 };
 
@@ -616,7 +624,7 @@ int cmdParse(
 
          break;
 
-      case 112: /* GDC  GPW  I2CC
+      case 112: /* BI2CC GDC  GPW  I2CC
                    I2CRB MG  MICS  MILS  MODEG  NC  NP  PFG  PRG
                    PROCD  PROCP  PROCS  PRRG  R  READ  SLRC  SPIC
                    WVDEL  WVSC  WVSM  WVSP  WVTX  WVTXR
@@ -787,7 +795,8 @@ int cmdParse(
 
          break;
 
-      case 131: /* HP I2CO  I2CPC  I2CRI  I2CWB  I2CWW  SLRO  SPIO  TRIG
+      case 131: /* BI2CO HP I2CO  I2CPC  I2CRI  I2CWB  I2CWW  SLRO
+                   SPIO  TRIG
 
                    Three positive parameters.
                 */
@@ -884,7 +893,7 @@ int cmdParse(
 
          break;
 
-      case 193: /* I2CWD  SERW
+      case 193: /* BI2CX  I2CWD  SERW  SPIW  SPIX
 
                    Two or more parameters, first >=0, rest 0-255.
                 */
index 08c5dd94137f39edc3e36525db64b9dd6610d98c..38180c51932ac8152fbb36912a3102e0f4099c23 100644 (file)
--- a/pigpio.3
+++ b/pigpio.3
@@ -2065,7 +2065,7 @@ 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
+For the SMBus commands the low level transactions are shown at the end
 of the function description.  The following abbreviations are used.
 
 .br
@@ -2191,7 +2191,7 @@ PI_I2C_WRITE_FAILED.
 .br
 
 .br
-Quick command. smbus 2.0 5.5.1
+Quick command. SMBus 2.0 5.5.1
 
 .EX
 S Addr Rd/Wr [A] P
@@ -2224,7 +2224,7 @@ PI_I2C_WRITE_FAILED.
 .br
 
 .br
-Send byte. smbus 2.0 5.5.2
+Send byte. SMBus 2.0 5.5.2
 
 .EX
 S Addr Wr [A] Data [A] P
@@ -2255,7 +2255,7 @@ or PI_I2C_READ_FAILED.
 .br
 
 .br
-Receive byte. smbus 2.0 5.5.3
+Receive byte. SMBus 2.0 5.5.3
 
 .EX
 S Addr Rd [A] [Data] NA P
@@ -2291,7 +2291,7 @@ PI_I2C_WRITE_FAILED.
 .br
 
 .br
-Write byte. smbus 2.0 5.5.4
+Write byte. SMBus 2.0 5.5.4
 
 .EX
 S Addr Wr [A] Comm [A] Data [A] P
@@ -2327,7 +2327,7 @@ PI_I2C_WRITE_FAILED.
 .br
 
 .br
-Write word. smbus 2.0 5.5.4
+Write word. SMBus 2.0 5.5.4
 
 .EX
 S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
@@ -2361,7 +2361,7 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 .br
 
 .br
-Read byte. smbus 2.0 5.5.5
+Read byte. SMBus 2.0 5.5.5
 
 .EX
 S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
@@ -2395,7 +2395,7 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 .br
 
 .br
-Read word. smbus 2.0 5.5.5
+Read word. SMBus 2.0 5.5.5
 
 .EX
 S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
@@ -2431,7 +2431,7 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 .br
 
 .br
-Process call. smbus 2.0 5.5.6
+Process call. SMBus 2.0 5.5.6
 
 .EX
 S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
@@ -2471,7 +2471,7 @@ PI_I2C_WRITE_FAILED.
 .br
 
 .br
-Block write. smbus 2.0 5.5.7
+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
@@ -2512,7 +2512,7 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 .br
 
 .br
-Block read. smbus 2.0 5.5.7
+Block read. SMBus 2.0 5.5.7
 
 .EX
 S Addr Wr [A] Comm [A]
@@ -2553,14 +2553,14 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 .br
 
 .br
-The smbus 2.0 documentation states that a minimum of 1 byte may be
+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
+Block write-block read. SMBus 2.0 5.5.8
 
 .EX
 S Addr Wr [A] Comm [A] Count [A] Data [A] ...
@@ -6815,6 +6815,18 @@ A 16-bit word value.
 #define PI_CMD_CF2   88
 .br
 
+.br
+#define PI_CMD_BI2CC 89
+.br
+#define PI_CMD_BI2CO 90
+.br
+#define PI_CMD_BI2CX 91
+.br
+
+.br
+#define PI_CMD_I2CX  92
+.br
+
 .br
 #define PI_CMD_NOIB  99
 .br
@@ -6905,7 +6917,7 @@ A 16-bit word value.
 .br
 #define PI_TOO_MANY_CHARS   -37 // waveform has too many chars
 .br
-#define PI_NOT_SERIAL_GPIO  -38 // no serial read in progress on gpio
+#define PI_NOT_SERIAL_GPIO  -38 // no bit bang serial read in progress on gpio
 .br
 #define PI_BAD_SERIAL_STRUC -39 // bad (null) serial structure parameter
 .br
@@ -7043,7 +7055,15 @@ A 16-bit word value.
 .br
 #define PI_BAD_I2C_PART    -106 // a combined I2C transaction failed
 .br
-
+#define PI_BAD_SMBUS_CMD   -107 // SMBus command not supported by driver
+.br
+#define PI_NOT_I2C_GPIO    -108 // no bit bang I2C in progress on gpio
+.br
+#define PI_BAD_BB_WLEN     -109 // bad BB write length
+.br
+#define PI_BAD_BB_RLEN     -110 // bad BB read length
+.br
+#define PI_BAD_BB_CMD      -111 // bad BB command
 .br
 
 .br
@@ -7092,7 +7112,7 @@ A 16-bit word value.
 .br
 #define PI_DEFAULT_UPDATE_MASK_R2        0xFBC7CF9C
 .br
-#define PI_DEFAULT_UPDATE_MASK_R3        0x0080400FFFFFFCLL
+#define PI_DEFAULT_UPDATE_MASK_R3        0x0080480FFFFFFCLL
 .br
 #define PI_DEFAULT_UPDATE_MASK_COMPUTE   0x00FFFFFFFFFFFFLL
 .br
index 920cb2f08b7f186f6391c57fed8a733d3927c778..b0fcaae7f485876366c7132ed454f31676f8482c 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 31 */
+/* pigpio version 32 */
 
 /* include ------------------------------------------------------- */
 
@@ -204,6 +204,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
    }
 
 #define CHECK_INITED                                               \
+   do                                                              \
    {                                                               \
       if (!libInitialised)                                         \
       {                                                            \
@@ -212,8 +213,10 @@ bit 0 READ_LAST_NOT_SET_ERROR
          return PI_NOT_INITIALISED;                                \
       }                                                            \
    }                                                               \
+   while (0)
 
 #define CHECK_INITED_RET_NULL_PTR                                  \
+   do                                                              \
    {                                                               \
       if (!libInitialised)                                         \
       {                                                            \
@@ -222,8 +225,10 @@ bit 0 READ_LAST_NOT_SET_ERROR
          return (NULL);                                            \
       }                                                            \
    }                                                               \
+   while (0)
 
 #define CHECK_INITED_RET_NIL                                       \
+   do                                                              \
    {                                                               \
       if (!libInitialised)                                         \
       {                                                            \
@@ -231,8 +236,10 @@ bit 0 READ_LAST_NOT_SET_ERROR
            "pigpio uninitialised, call gpioInitialise()");         \
       }                                                            \
    }                                                               \
+   while (0)
 
 #define CHECK_NOT_INITED                                           \
+   do                                                              \
    {                                                               \
       if (libInitialised)                                          \
       {                                                            \
@@ -241,14 +248,18 @@ bit 0 READ_LAST_NOT_SET_ERROR
          return PI_INITIALISED;                                    \
       }                                                            \
    }                                                               \
+   while (0)
 
 #define SOFT_ERROR(x, format, arg...)                              \
+   do                                                              \
    {                                                               \
       DBG(DBG_ALWAYS, format, ## arg);                             \
       return x;                                                    \
    }                                                               \
+   while (0)
 
 #define TIMER_ADD(a, b, result)                                    \
+   do                                                              \
    {                                                               \
       (result)->tv_sec =  (a)->tv_sec  + (b)->tv_sec;              \
       (result)->tv_nsec = (a)->tv_nsec + (b)->tv_nsec;             \
@@ -258,8 +269,10 @@ bit 0 READ_LAST_NOT_SET_ERROR
         (result)->tv_nsec -= BILLION;                              \
       }                                                            \
    }                                                               \
+   while (0)
 
 #define TIMER_SUB(a, b, result)                                    \
+   do                                                              \
    {                                                               \
       (result)->tv_sec =  (a)->tv_sec  - (b)->tv_sec;              \
       (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec;             \
@@ -269,6 +282,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
          (result)->tv_nsec += BILLION;                             \
       }                                                            \
    }                                                               \
+   while (0)
 
 #define PI_PERI_BUS 0x7E000000
 
@@ -688,8 +702,11 @@ bit 0 READ_LAST_NOT_SET_ERROR
 #define PI_NOTIFY_RUNNING 3
 #define PI_NOTIFY_PAUSED  4
 
-#define PI_WFRX_NONE   0
-#define PI_WFRX_SERIAL 1
+#define PI_WFRX_NONE    0
+#define PI_WFRX_SERIAL  1
+#define PI_WFRX_I2C     2
+#define PI_WFRX_I2C_CLK 3
+
 #define PI_WF_MICROS   1
 
 #define DATUMS 2000
@@ -700,9 +717,12 @@ bit 0 READ_LAST_NOT_SET_ERROR
 
 #define SRX_BUF_SIZE 8192
 
-#define PI_I2C_SLAVE 0x0703
-#define PI_I2C_RDWR  0x0707
-#define PI_I2C_SMBUS 0x0720
+#define PI_I2C_RETRIES 0x0701
+#define PI_I2C_TIMEOUT 0x0702
+#define PI_I2C_SLAVE   0x0703
+#define PI_I2C_FUNCS   0x0705
+#define PI_I2C_RDWR    0x0707
+#define PI_I2C_SMBUS   0x0720
 
 #define PI_I2C_SMBUS_READ  1
 #define PI_I2C_SMBUS_WRITE 0
@@ -720,6 +740,19 @@ bit 0 READ_LAST_NOT_SET_ERROR
 #define PI_I2C_SMBUS_BLOCK_MAX     32
 #define PI_I2C_SMBUS_I2C_BLOCK_MAX 32
 
+#define PI_I2C_FUNC_SMBUS_QUICK            0x00010000
+#define PI_I2C_FUNC_SMBUS_READ_BYTE        0x00020000
+#define PI_I2C_FUNC_SMBUS_WRITE_BYTE       0x00040000
+#define PI_I2C_FUNC_SMBUS_READ_BYTE_DATA   0x00080000
+#define PI_I2C_FUNC_SMBUS_WRITE_BYTE_DATA  0x00100000
+#define PI_I2C_FUNC_SMBUS_READ_WORD_DATA   0x00200000
+#define PI_I2C_FUNC_SMBUS_WRITE_WORD_DATA  0x00400000
+#define PI_I2C_FUNC_SMBUS_PROC_CALL        0x00800000
+#define PI_I2C_FUNC_SMBUS_READ_BLOCK_DATA  0x01000000
+#define PI_I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
+#define PI_I2C_FUNC_SMBUS_READ_I2C_BLOCK   0x04000000
+#define PI_I2C_FUNC_SMBUS_WRITE_I2C_BLOCK  0x08000000
+
 #define PI_MASH_MAX_FREQ 23800000
 
 #define FLUSH_PAGES 1024
@@ -764,6 +797,10 @@ bit 0 READ_LAST_NOT_SET_ERROR
 #define PI_SPI_FLAGS_GET_CSPOLS(x)  (((x)>>2)&7)
 #define PI_SPI_FLAGS_GET_MODE(x)     ((x)&3)
 
+#define PI_STARTING 0
+#define PI_RUNNING  1
+#define PI_ENDING   2
+
 /* typedef ------------------------------------------------------- */
 
 typedef void (*callbk_t) ();
@@ -862,6 +899,7 @@ typedef struct
    uint16_t seqno;
    uint16_t state;
    uint32_t bits;
+   uint32_t lastReportTick;
    int      fd;
    int      pipe;
 } gpioNotify_t;
@@ -871,6 +909,7 @@ typedef struct
    uint16_t state;
    int16_t  fd;
    uint32_t flags;
+   uint32_t funcs;
 } i2cInfo_t;
 
 typedef struct
@@ -931,12 +970,10 @@ typedef struct
 
 typedef struct
 {
-   int      gpio;
    char    *buf;
    uint32_t bufSize;
    int      readPos;
    int      writePos;
-   uint32_t baud; /* 50-250000 */
    uint32_t fullBit; /* nanoseconds */
    uint32_t halfBit; /* nanoseconds */
    int      timeout; /* millisconds */
@@ -946,8 +983,29 @@ typedef struct
    uint32_t data;
    int      bytes; /* 1, 2, 4 */
    int      level;
-   int      mode;
    int      dataBits; /* 1-32 */
+} wfRxSerial_t;
+
+typedef struct
+{
+   int SDA;
+   int SCL;
+   int delay;
+   int SDAMode;
+   int SCLMode;
+   int started;
+} wfRxI2C_t;
+
+typedef struct
+{
+   int      mode;
+   int      gpio;
+   uint32_t baud; /* 50-250000 */
+   union
+   {
+      wfRxSerial_t s;
+      wfRxI2C_t    I;
+   };
 } wfRx_t;
 
 union my_smbus_data
@@ -1038,8 +1096,7 @@ static volatile uint32_t monitorBits = 0;
 static volatile uint32_t notifyBits  = 0;
 static volatile uint32_t scriptBits  = 0;
 
-static volatile int DMAstarted = 0;
-static volatile int terminating = 0;
+static volatile int runState = PI_STARTING;
 
 static int pthAlertRunning  = 0;
 static int pthFifoRunning   = 0;
@@ -1278,11 +1335,33 @@ static char * myTimeStamp()
 
 /* ----------------------------------------------------------------------- */
 
+static char *myBuf2Str(unsigned count, char *buf)
+{
+   static char str[128];
+   int i, c;
+
+   if (count && buf)
+   {
+      if (count > 40) c = 40; else c = count;
+
+      for (i=0; i<c; i++) sprintf(str+(3*i), "%02X ", buf[i]);
+      str[(3*c)-1] = 0;
+   }
+   else str[0] = 0;
+
+   return str;
+}
+
+/* ----------------------------------------------------------------------- */
+
 static int my_smbus_access(
    int fd, char rw, uint8_t cmd, int size, union my_smbus_data *data)
 {
    struct my_smbus_ioctl_data args;
 
+   DBG(DBG_INTERNAL, "rw=%d reg=%d cmd=%d data=%s",
+      rw, cmd, size, myBuf2Str(data->byte+1, (char*)data));
+
    args.read_write = rw;
    args.command    = cmd;
    args.size       = size;
@@ -1293,23 +1372,18 @@ static int my_smbus_access(
 
 /* ----------------------------------------------------------------------- */
 
-static char *myBuf2Str(unsigned count, char *buf)
+static void myGpioSetMode(unsigned gpio, unsigned mode)
 {
-   static char str[64];
-   int i, c;
-
-   if (count)
-   {
-      if (count > 10) c = 10; else c = count;
+   int reg, shift;
 
-      for (i=0; i<c; i++) sprintf(str+(3*i), "%02X ", buf[i]);
-      str[(3*c)-1] = 0;
-   }
-   else str[0] = 0;
+   reg   =  gpio/10;
+   shift = (gpio%10) * 3;
 
-   return str;
+   gpioReg[reg] = (gpioReg[reg] & ~(7<<shift)) | (mode<<shift);
 }
 
+
+
 /* ----------------------------------------------------------------------- */
 
 static void myGpioWrite(unsigned gpio, unsigned level)
@@ -1456,9 +1530,9 @@ static void flushMemory(void)
 
 /* ----------------------------------------------------------------------- */
 
-static void waitForDMAstarted(void)
+static void spinWhileStarting(void)
 {
-   while ((!DMAstarted) && (!terminating))
+   while (runState == PI_STARTING)
    {
       if (piModel == 1) myGpioDelay(1000);
       else flushMemory();
@@ -1507,6 +1581,23 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
          }
          break;
 
+      case PI_CMD_BI2CC: res = bbI2CClose(p[1]); break;
+
+      case PI_CMD_BI2CO:
+         memcpy(&p[4], buf, 4);
+         res = bbI2COpen(p[1], p[2], p[4]);
+         break;
+
+      case PI_CMD_BI2CX:
+         /* use half buffer for write, half buffer for read */
+         if (p[3] > (bufSize/2)) p[3] = bufSize/2;
+         res = bbI2CXfer(p[1], buf, p[3], buf+(bufSize/2), bufSize/2);
+         if (res > 0)
+         {
+            memcpy(buf, buf+(bufSize/2), res);
+         }
+         break;
+
       case PI_CMD_BR1: res = gpioRead_Bits_0_31(); break;
 
       case PI_CMD_BR2: res = gpioRead_Bits_32_53(); break;
@@ -2164,7 +2255,7 @@ static unsigned mbAllocateMemory(
    p[i++] = align;
    p[i++] = flags;
    p[i++] = MB_END_TAG;
-   p[0] = i*sizeof *p;
+   p[0] = i*sizeof(*p);
 
    mbProperty(fd, p);
 
@@ -2182,7 +2273,7 @@ static unsigned mbLockMemory(int fd, unsigned handle)
    p[i++] = 4;
    p[i++] = handle;
    p[i++] = MB_END_TAG;
-   p[0] = i*sizeof *p;
+   p[0] = i*sizeof(*p);
 
    mbProperty(fd, p);
 
@@ -2200,7 +2291,7 @@ static unsigned mbUnlockMemory(int fd, unsigned handle)
    p[i++] = 4;
    p[i++] = handle;
    p[i++] = MB_END_TAG;
-   p[0] = i*sizeof *p;
+   p[0] = i*sizeof(*p);
 
    mbProperty(fd, p);
 
@@ -2218,7 +2309,7 @@ static unsigned mbReleaseMemory(int fd, unsigned handle)
    p[i++] = 4;
    p[i++] = handle;
    p[i++] = MB_END_TAG;
-   p[0] = i*sizeof *p;
+   p[0] = i*sizeof(*p);
 
    mbProperty(fd, p);
 
@@ -2608,56 +2699,57 @@ static int wave2Cbs(unsigned wave_mode)
 
 /* ----------------------------------------------------------------------- */
 
-static void waveRxSerial(wfRx_t *s, int level, uint32_t tick)
+static void waveRxSerial(wfRx_t *w, int level, uint32_t tick)
 {
    int diffTicks, lastLevel;
    int newWritePos;
 
-   if (s->bit >= 0)
+   if (w->s.bit >= 0)
    {
-      diffTicks = tick - s->startBitTick;
+      diffTicks = tick - w->s.startBitTick;
 
       if (level != PI_TIMEOUT)
       {
-         s->level = level;
+         w->s.level = level;
          lastLevel = !level;
       }
-      else lastLevel = s->level;
+      else lastLevel = w->s.level;
 
-      while ((s->bit <= s->dataBits) && (diffTicks > (s->nextBitDiff/1000)))
+      while ((w->s.bit <= w->s.dataBits) &&
+             (diffTicks > (w->s.nextBitDiff/1000)))
       {
-         if (s->bit)
+         if (w->s.bit)
          {
-            if (lastLevel) s->data |= (1<<(s->bit-1));
+            if (lastLevel) w->s.data |= (1<<(w->s.bit-1));
          }
-         else s->data = 0;
+         else w->s.data = 0;
 
-         ++(s->bit);
+         ++(w->s.bit);
 
-         s->nextBitDiff += s->fullBit;
+         w->s.nextBitDiff += w->s.fullBit;
       }
 
-      if (s->bit > s->dataBits)
+      if (w->s.bit > w->s.dataBits)
       {
-         memcpy(s->buf + s->writePos, &s->data, s->bytes);
+         memcpy(w->s.buf + w->s.writePos, &w->s.data, w->s.bytes);
 
          /* don't let writePos catch readPos */
 
-         newWritePos = (s->writePos + s->bytes) % (s->bufSize);
+         newWritePos = (w->s.writePos + w->s.bytes) % (w->s.bufSize);
 
-         if (newWritePos != s->readPos) s->writePos = newWritePos;
+         if (newWritePos != w->s.readPos) w->s.writePos = newWritePos;
 
          if (level == 0)
          {
-            gpioSetWatchdog(s->gpio, s->timeout);
-            s->bit          = 0;
-            s->startBitTick = tick;
-            s->nextBitDiff  = s->halfBit;
+            gpioSetWatchdog(w->gpio, w->s.timeout);
+            w->s.bit          = 0;
+            w->s.startBitTick = tick;
+            w->s.nextBitDiff  = w->s.halfBit;
          }
          else
          {
-            s->bit = -1;
-            gpioSetWatchdog(s->gpio, 0);
+            w->s.bit = -1;
+            gpioSetWatchdog(w->gpio, 0);
          }
       }
    }
@@ -2667,11 +2759,11 @@ static void waveRxSerial(wfRx_t *s, int level, uint32_t tick)
 
       if (level == 0)
       {
-         gpioSetWatchdog(s->gpio, s->timeout);
-         s->level        = 0;
-         s->bit          = 0;
-         s->startBitTick = tick;
-         s->nextBitDiff  = s->halfBit;
+         gpioSetWatchdog(w->gpio, w->s.timeout);
+         w->s.level        = 0;
+         w->s.bit          = 0;
+         w->s.startBitTick = tick;
+         w->s.nextBitDiff  = w->s.halfBit;
       }
    }
 }
@@ -2683,9 +2775,6 @@ static void waveRxBit(int gpio, int level, uint32_t tick)
 {
    switch (wfRx[gpio].mode)
    {
-      case PI_WFRX_NONE:
-         break;
-
       case PI_WFRX_SERIAL:
          waveRxSerial(&wfRx[gpio], level, tick);
    }
@@ -2846,6 +2935,9 @@ int i2cWriteQuick(unsigned handle, unsigned bit)
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_QUICK) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (bit > 1)
       SOFT_ERROR(PI_BAD_PARAM, "bad bit (%d)", bit);
 
@@ -2871,6 +2963,9 @@ int i2cReadByte(unsigned handle)
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_BYTE) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (my_smbus_access(
       i2cInfo[handle].fd, PI_I2C_SMBUS_READ, 0, PI_I2C_SMBUS_BYTE, &data))
       return PI_I2C_READ_FAILED;
@@ -2893,6 +2988,9 @@ int i2cWriteByte(unsigned handle, unsigned bVal)
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_WRITE_BYTE) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (bVal > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad bVal (%d)", bVal);
 
@@ -2923,6 +3021,9 @@ int i2cReadByteData(unsigned handle, unsigned reg)
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_BYTE_DATA) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (reg > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
 
@@ -2950,6 +3051,9 @@ int i2cWriteByteData(unsigned handle, unsigned reg, unsigned bVal)
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_WRITE_BYTE_DATA) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (reg > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
 
@@ -2985,11 +3089,18 @@ int i2cReadWordData(unsigned handle, unsigned reg)
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_WORD_DATA) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (reg > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
 
    if (my_smbus_access(
-      i2cInfo[handle].fd, PI_I2C_SMBUS_READ, reg, PI_I2C_SMBUS_WORD_DATA, &data))
+      i2cInfo[handle].fd,
+      PI_I2C_SMBUS_READ,
+      reg,
+      PI_I2C_SMBUS_WORD_DATA,
+      &data))
       return PI_I2C_READ_FAILED;
    else
       return 0xFFFF & data.word;
@@ -3012,6 +3123,9 @@ int i2cWriteWordData(unsigned handle, unsigned reg, unsigned wVal)
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_WRITE_WORD_DATA) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (reg > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
 
@@ -3047,6 +3161,9 @@ int i2cProcessCall(unsigned handle, unsigned reg, unsigned wVal)
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_PROC_CALL) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (reg > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
 
@@ -3056,7 +3173,10 @@ int i2cProcessCall(unsigned handle, unsigned reg, unsigned wVal)
    data.word = wVal;
 
    if (my_smbus_access(
-      i2cInfo[handle].fd, PI_I2C_SMBUS_WRITE, reg, PI_I2C_SMBUS_PROC_CALL, &data))
+      i2cInfo[handle].fd,
+      PI_I2C_SMBUS_WRITE,
+      reg, PI_I2C_SMBUS_PROC_CALL,
+      &data))
       return PI_I2C_READ_FAILED;
    else
       return 0xFFFF & data.word;
@@ -3079,11 +3199,18 @@ int i2cReadBlockData(unsigned handle, unsigned reg, char *buf)
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_BLOCK_DATA) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (reg > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
 
    if (my_smbus_access(
-      i2cInfo[handle].fd, PI_I2C_SMBUS_READ, reg, PI_I2C_SMBUS_BLOCK_DATA, &data))
+      i2cInfo[handle].fd,
+      PI_I2C_SMBUS_READ,
+      reg,
+      PI_I2C_SMBUS_BLOCK_DATA,
+      &data))
       return PI_I2C_READ_FAILED;
    else
    {
@@ -3115,6 +3242,9 @@ int i2cWriteBlockData(
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (reg > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
 
@@ -3155,6 +3285,9 @@ int i2cBlockProcessCall(
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_PROC_CALL) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (reg > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
 
@@ -3198,6 +3331,9 @@ int i2cReadI2CBlockData(
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_I2C_BLOCK) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (reg > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
 
@@ -3243,6 +3379,9 @@ int i2cWriteI2CBlockData(
    if (i2cInfo[handle].state == PI_I2C_CLOSED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
+   if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) == 0)
+      SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
    if (reg > 0xFF)
       SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
 
@@ -3321,6 +3460,7 @@ int i2cOpen(unsigned i2cBus, unsigned i2cAddr, unsigned i2cFlags)
 {
    char dev[32];
    int i, slot, fd;
+   uint32_t funcs;
 
    DBG(DBG_USER, "i2cBus=%d i2cAddr=%d flags=0x%X",
       i2cBus, i2cAddr, i2cFlags);
@@ -3330,8 +3470,8 @@ int i2cOpen(unsigned i2cBus, unsigned i2cAddr, unsigned i2cFlags)
    if (i2cBus >= PI_NUM_I2C_BUS)
       SOFT_ERROR(PI_BAD_I2C_BUS, "bad I2C bus (%d)", i2cBus);
 
-   if ((i2cAddr < 0x08) || (i2cAddr > 0x77))
-      SOFT_ERROR(PI_BAD_I2C_ADDR, "bad I2C address (0x%X)", i2cAddr);
+//   if ((i2cAddr < 0x08) || (i2cAddr > 0x77))
+//      SOFT_ERROR(PI_BAD_I2C_ADDR, "bad I2C address (0x%X)", i2cAddr);
 
    if (i2cFlags)
       SOFT_ERROR(PI_BAD_FLAGS, "bad flags (0x%X)", i2cFlags);
@@ -3376,8 +3516,14 @@ int i2cOpen(unsigned i2cBus, unsigned i2cAddr, unsigned i2cFlags)
       return PI_I2C_OPEN_FAILED;
    }
 
+   if (ioctl(fd, PI_I2C_FUNCS, &funcs) < 0)
+   {
+      funcs = -1; /* assume all smbus commands allowed */
+   }
+
    i2cInfo[slot].fd = fd;
    i2cInfo[slot].flags = i2cFlags;
+   i2cInfo[slot].funcs = funcs;
 
    return slot;
 }
@@ -3404,7 +3550,7 @@ int i2cClose(unsigned handle)
 
 int i2cTransaction(unsigned handle, pi_i2c_msg_t *parts, unsigned numParts)
 {
-   int retval, fd;
+   int retval;
    my_i2c_rdwr_ioctl_data_t rdwr;
 
    DBG(DBG_USER, "handle=%d", handle);
@@ -3423,14 +3569,6 @@ int i2cTransaction(unsigned handle, pi_i2c_msg_t *parts, unsigned numParts)
    if (numParts > PI_I2C_RDRW_IOCTL_MAX_MSGS)
       SOFT_ERROR(PI_TOO_MANY_PARTS, "too many parts (%d)", numParts);
 
-   fd = open(PI_I2C_COMBINED, O_RDWR);
-
-   if (fd >= 0)
-   {
-      write(fd, "1", 1);
-      close(fd);
-   }
-
    rdwr.msgs = parts;
    rdwr.nmsgs = numParts;
 
@@ -3442,6 +3580,129 @@ int i2cTransaction(unsigned handle, pi_i2c_msg_t *parts, unsigned numParts)
    else             return PI_BAD_I2C_PART;
 }
 
+#ifdef ZZZZ
+
+int i2cXfer(
+   unsigned handle,
+   char *inBuf, unsigned inLen, char *outBuf, unsigned outLen)
+{
+   int i, parts, inPos, outPos, status, bytes, len_bytes,flags, addr;
+   pi_i2c_msg_t part[PI_I2C_RDRW_IOCTL_MAX_MSGS];
+
+   DBG(DBG_USER, "handle=%d inBuf=%s outBuf=%08X len=%d",
+      handle, myBuf2Str(inLen, (char *)inBuf), (int)outBuf, outLen);
+
+   CHECK_INITED;
+
+   if (handle >= PI_I2C_SLOTS)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+   if (i2cInfo[handle].state != PI_I2C_OPENED)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+   if (!inBuf || !inLen)
+      SOFT_ERROR(PI_BAD_POINTER, "input buffer can't be NULL");
+
+   if (!outBuf && outLen)
+      SOFT_ERROR(PI_BAD_POINTER, "output buffer can't be NULL");
+
+   parts = 0;
+   inPos = 0;
+   outPos = 0;
+   status = 0;
+   flags = 0;
+   addr = 0;
+
+   while (!status && (inPos < inLen) && (parts < PI_I2C_RDRW_IOCTL_MAX_MSGS))
+   {
+      DBG(DBG_INTERNAL, "status=%d inpos=%d inlen=%d cmd=%d",
+         status, inPos, inLen, inBuf[inPos]);
+
+      len_bytes = 1;
+
+      switch (inBuf[inPos++])
+      {
+         case PI_I2C_END:
+            status = 1;
+            break;
+
+         case PI_I2C_READ16:
+            len_bytes = 2;
+            /* fall through */
+
+         case PI_I2C_READ:
+            if (inPos <= (inLen - len_bytes))
+            {
+               if (len_bytes != 1)
+               {
+                  bytes=inBuf[inPos] + (inBuf[inPos+1]<<8);
+                  inPos += 2;
+               }
+               else
+               {
+                  bytes=inBuf[inPos++];
+               }
+
+               if (bytes && ((bytes + outPos) < outLen))
+               {
+                  part[parts].addr = addr;
+                  part[parts].flags = flags;
+                  part[parts].len =
+                  part[parts].buf =
+
+                  for (i=0; i<(bytes-1); i++)
+                  {
+                     outBuf[outPos++] = I2CGetByte(w, 0);
+                  }
+                  outBuf[outPos++] = I2CGetByte(w, 1);
+               }
+               else status = PI_BAD_BB_WLEN;
+            }
+            else status = PI_BAD_BB_WLEN;
+            break;
+
+         case PI_I2C_WRITE16:
+            len_bytes = 2;
+            /* fall through */
+
+         case PI_I2C_WRITE:
+            if (inPos <= (inLen - len_bytes))
+            {
+               if (len_bytes != 1)
+               {
+                  bytes=inBuf[inPos] + (inBuf[inPos+1]<<8);
+                  inPos += 2;
+               }
+               else
+               {
+                  bytes=inBuf[inPos++];
+               }
+
+               if (bytes && ((bytes + inPos) < inLen))
+               {
+                  for (i=0; i<(bytes-1); i++)
+                  {
+                     ack = I2CPutByte(w, inBuf[inPos++]);
+                     if (ack) status = PI_I2C_WRITE_FAILED;
+                  }
+                  ack = I2CPutByte(w, inBuf[inPos++]);
+                  //if (ack) status = PI_I2C_WRITE_FAILED;
+               }
+               else status = PI_BAD_BB_RLEN;
+            }
+            else status = PI_BAD_BB_RLEN;
+            break;
+
+         default:
+            status = PI_BAD_BB_CMD;
+      }
+   }
+
+   if (status >= 0) status = outPos;
+
+   return status;
+}
+#endif
 
 /* ======================================================================= */
 
@@ -4682,7 +4943,7 @@ static void * pthAlertThread(void *x)
 
    /* don't start until DMA started */
 
-   waitForDMAstarted();
+   spinWhileStarting();
 
    reportedLevel = gpioReg[GPLEV0];
 
@@ -4714,7 +4975,7 @@ static void * pthAlertThread(void *x)
 
          myGpioDelay(5000);
 
-         if (DMAstarted)
+         if (runState == PI_RUNNING)
          {
             /* should never be executed, leave code just in case */
 
@@ -4897,11 +5158,13 @@ static void * pthAlertThread(void *x)
                {
                   if (gpioAlert[b].ex)
                   {
-                     (gpioAlert[b].func)(b, 2, tick, gpioAlert[b].userdata);
+                     (gpioAlert[b].func)
+                        (b, PI_TIMEOUT, tick, gpioAlert[b].userdata);
                   }
                   else
                   {
-                     (gpioAlert[b].func)(b, 2, tick);
+                     (gpioAlert[b].func)
+                        (b, PI_TIMEOUT, tick);
                   }
                }
             }
@@ -4985,7 +5248,7 @@ static void * pthAlertThread(void *x)
 
                      gpioReport[emit].seqno = seqno;
                      gpioReport[emit].flags = PI_NTFY_FLAGS_WDOG |
-                                          PI_NTFY_FLAGS_BIT(b);
+                                              PI_NTFY_FLAGS_BIT(b);
                      gpioReport[emit].tick  = tick;
                      gpioReport[emit].level = newLevel;
 
@@ -4995,8 +5258,29 @@ static void * pthAlertThread(void *x)
                }
             }
 
+            if (!emit)
+            {
+               if ((tick - gpioNotify[n].lastReportTick) > 60000000)
+               {
+                  if (numSamples)
+                     newLevel = gpioSample[numSamples-1].level;
+                  else
+                     newLevel = reportedLevel;
+
+                  gpioReport[emit].seqno = seqno;
+                  gpioReport[emit].flags = PI_NTFY_FLAGS_ALIVE;
+                  gpioReport[emit].tick  = tick;
+                  gpioReport[emit].level = newLevel;
+
+                  emit++;
+                  seqno++;
+               }
+            }
+
             if (emit)
             {
+               gpioNotify[n].lastReportTick = tick;
+
                if (emit > gpioStats.maxEmit) gpioStats.maxEmit = emit;
 
                emitted = 0;
@@ -5496,7 +5780,7 @@ static void * pthFifoThread(void *x)
 
    /* don't start until DMA started */
 
-   waitForDMAstarted();
+   spinWhileStarting();
 
    while (1)
    {
@@ -5665,6 +5949,7 @@ static void *pthSocketThreadHandler(void *fdC)
       {
          /* extensions */
 
+         case PI_CMD_BI2CX:
          case PI_CMD_CF2:
          case PI_CMD_I2CPK:
          case PI_CMD_I2CRD:
@@ -5721,7 +6006,7 @@ static void * pthSocketThread(void *x)
 
    /* don't start until DMA started */
 
-   waitForDMAstarted();
+   spinWhileStarting();
 
    while ((fdC =
       accept(fdSock, (struct sockaddr *)&client, (socklen_t*)&c)))
@@ -5794,7 +6079,7 @@ static int initCheckPermitted(void)
 
    if ((fdMem = open("/dev/mem", O_RDWR | O_SYNC) ) < 0)
    {
-      DBG(DBG_STARTUP,
+      DBG(DBG_ALWAYS,
          "\n" \
          "+---------------------------------------------------------+\n" \
          "|Sorry, you don't have permission to run this program.    |\n" \
@@ -6375,10 +6660,6 @@ static void initClearGlobals(void)
    notifyBits  = 0;
    scriptBits  = 0;
 
-   libInitialised = 0;
-   DMAstarted     = 0;
-   terminating    = 0;
-
    pthAlertRunning  = 0;
    pthFifoRunning   = 0;
    pthSocketRunning = 0;
@@ -6642,8 +6923,6 @@ int initInitialise(void)
 
    DBG(DBG_STARTUP, "");
 
-   if (libInitialised) return PIGPIO_VERSION;
-
    waveClockInited = 0;
 
    clock_gettime(CLOCK_REALTIME, &libStarted);
@@ -6692,8 +6971,6 @@ int initInitialise(void)
 
    initClock(1); /* initialise main clock */
 
-   libInitialised = 1;
-
    atexit(gpioTerminate);
 
    if (pthread_attr_init(&pthAttr))
@@ -6749,8 +7026,6 @@ int initInitialise(void)
 
    myGpioDelay(20000);
 
-   DMAstarted = 1;
-
    return PIGPIO_VERSION;
 }
 
@@ -6956,12 +7231,22 @@ int gpioInitialise(void)
 {
    int status;
 
+   if (libInitialised) return PIGPIO_VERSION;
+
+   runState = PI_STARTING;
+
    status = initInitialise();
 
    if (status < 0)
    {
+      runState = PI_ENDING;
       initReleaseResources();
    }
+   else
+   {
+      libInitialised = 1;
+      runState = PI_RUNNING;
+   }
 
    return status;
 }
@@ -6975,58 +7260,54 @@ void gpioTerminate(void)
 
    DBG(DBG_USER, "");
 
-   terminating = 1;
-
-   if (libInitialised)
-   {
-      libInitialised = 0;
+   if (!libInitialised) return;
 
-      gpioMaskSet = 0;
+   runState = PI_ENDING;
 
-      /* reset DMA */
+   gpioMaskSet = 0;
 
-      DMAstarted = 0;
+   /* reset DMA */
 
-      dmaIn[DMA_CS] = DMA_CHANNEL_RESET;
-      dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
+   if (dmaReg != MAP_FAILED) dmaIn[DMA_CS] = DMA_CHANNEL_RESET;
+   if (dmaReg != MAP_FAILED) dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
 
 #ifndef EMBEDDED_IN_VM
-      if (gpioCfg.showStats)
-      {
-         fprintf(stderr,
-            "If you didn't request stats please cut & paste the\n"
-            "following and e-mail to pigpio@abyz.co.uk\n");
+   if (gpioCfg.showStats)
+   {
+      fprintf(stderr,
+         "If you didn't request stats please cut & paste the\n"
+         "following and e-mail to pigpio@abyz.co.uk\n");
 
-         fprintf(stderr,
-            "#####################################################\n");
+      fprintf(stderr,
+         "micros=%d allocMode=%d dmaInitCbs=%d DMARestarts=%d\n",
+         gpioCfg.clockMicros, gpioCfg.memAllocMode,
+         gpioStats.dmaInitCbsCount, gpioStats.DMARestarts);
 
-         fprintf(stderr,
-            "micros=%d allocMode=%d dmaInitCbs=%d DMARestarts=%d\n",
-             gpioCfg.clockMicros, gpioCfg.memAllocMode,
-             gpioStats.dmaInitCbsCount, gpioStats.DMARestarts);
+      fprintf(stderr,
+         "samples %u maxSamples %u maxEmit %u emitFrags %u\n",
+         gpioStats.numSamples, gpioStats.maxSamples,
+         gpioStats.maxEmit, gpioStats.emitFrags);
 
-         fprintf(stderr,
-            "samples %u maxSamples %u maxEmit %u emitFrags %u\n",
-            gpioStats.numSamples, gpioStats.maxSamples,
-            gpioStats.maxEmit, gpioStats.emitFrags);
+      fprintf(stderr, "cbTicks %d, cbCalls %u alertTicks %u\n",
+         gpioStats.cbTicks, gpioStats.cbCalls, gpioStats.alertTicks);
 
-         fprintf(stderr, "cbTicks %d, cbCalls %u alertTicks %u\n",
-            gpioStats.cbTicks, gpioStats.cbCalls, gpioStats.alertTicks);
+      for (i=0; i< TICKSLOTS; i++)
+         fprintf(stderr, "%9u ", gpioStats.diffTick[i]);
 
-         for (i=0; i< TICKSLOTS; i++)
-            fprintf(stderr, "%9u ", gpioStats.diffTick[i]);
+      fprintf(stderr, "\n");
 
-         fprintf(stderr, "\n");
+      fprintf(stderr, "\n");
 
-         fprintf(stderr,
-            "#####################################################\n");
-      }
-#endif
+      fprintf(stderr,
+         "#####################################################\n");
    }
+#endif
 
    initReleaseResources();
 
    fflush(NULL);
+
+   libInitialised = 0;
 }
 
 static void switchFunctionOff(unsigned gpio)
@@ -8117,6 +8398,332 @@ int gpioWaveGetMaxCbs(void)
    return wfStats.maxCbs;
 }
 
+static int read_SDA(wfRx_t *w)
+{
+   myGpioSetMode(w->I.SDA, PI_INPUT);
+   return gpioRead(w->I.SDA);
+}
+
+static void set_SDA(wfRx_t *w)
+{
+   myGpioSetMode(w->I.SDA, PI_INPUT);
+}
+
+static void clear_SDA(wfRx_t *w)
+{
+   myGpioSetMode(w->I.SDA, PI_OUTPUT);
+   myGpioWrite(w->I.SDA, 0);
+}
+
+static void clear_SCL(wfRx_t *w)
+{
+   myGpioSetMode(w->I.SCL, PI_OUTPUT);
+   myGpioWrite(w->I.SCL, 0);
+}
+
+static void I2C_delay(wfRx_t *w)
+{
+   myGpioDelay(w->I.delay);
+}
+
+static void I2C_clock_stretch(wfRx_t *w)
+{
+   uint32_t now, max_stretch=10000;
+
+   myGpioSetMode(w->I.SCL, PI_INPUT);
+   now = gpioTick();
+   while ((gpioRead(w->I.SCL) == 0) && ((gpioTick()-now) < max_stretch));
+}
+
+static void I2CStart(wfRx_t *w)
+{
+   if (w->I.started)
+   {
+      set_SDA(w);
+      I2C_delay(w);
+      I2C_clock_stretch(w);
+      I2C_delay(w);
+   }
+
+   clear_SDA(w);
+   I2C_delay(w);
+   clear_SCL(w);
+   I2C_delay(w);
+
+   w->I.started = 1;
+}
+
+static void I2CStop(wfRx_t *w)
+{
+   clear_SDA(w);
+   I2C_delay(w);
+   I2C_clock_stretch(w);
+   I2C_delay(w);
+   set_SDA(w);
+   I2C_delay(w);
+
+   w->I.started = 0;
+}
+
+static void I2CPutBit(wfRx_t *w, int bit)
+{
+   if (bit) set_SDA(w);
+   else     clear_SDA(w);
+
+   I2C_delay(w);
+   I2C_clock_stretch(w);
+   I2C_delay(w);
+   clear_SCL(w);
+}
+
+static int I2CGetBit(wfRx_t *w)
+{
+   int bit;
+
+   set_SDA(w); /* let SDA float */
+   I2C_delay(w);
+   I2C_clock_stretch(w);
+   bit = read_SDA(w);
+   I2C_delay(w);
+   clear_SCL(w);
+
+   return bit;
+}
+
+static int I2CPutByte(wfRx_t *w, int byte)
+{
+   int bit, nack;
+
+   for(bit=0; bit<8; bit++)
+   {
+      I2CPutBit(w, byte & 0x80);
+      byte <<= 1;
+   }
+
+   nack = I2CGetBit(w);
+
+   return nack;
+}
+
+static uint8_t I2CGetByte(wfRx_t *w, int nack)
+{
+   int bit, byte=0;
+
+   for (bit=0; bit<8; bit++)
+   {
+      byte = (byte << 1) | I2CGetBit(w);
+   }
+
+   I2CPutBit(w, nack);
+
+   return byte;
+}
+
+int bbI2COpen(unsigned SDA, unsigned SCL, unsigned bbBaud)
+{
+   DBG(DBG_USER, "SDA=%d SCL=%d bbBaud=%d", SDA, SCL, bbBaud);
+
+   CHECK_INITED;
+
+   if (SDA > PI_MAX_USER_GPIO)
+      SOFT_ERROR(PI_BAD_USER_GPIO, "bad SDA (%d)", SDA);
+
+   if (SCL > PI_MAX_USER_GPIO)
+      SOFT_ERROR(PI_BAD_USER_GPIO, "bad SCL (%d)", SCL);
+
+   if ((bbBaud < PI_BB_MIN_BAUD) || (bbBaud > PI_BB_RX_MAX_BAUD))
+      SOFT_ERROR(PI_BAD_WAVE_BAUD,
+         "SDA %d, bad baud rate (%d)", SDA, bbBaud);
+
+   if (wfRx[SDA].mode != PI_WFRX_NONE)
+      SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used", SDA);
+
+   if (wfRx[SCL].mode != PI_WFRX_NONE)
+      SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used", SCL);
+
+   wfRx[SDA].gpio = SDA;
+   wfRx[SDA].mode = PI_WFRX_I2C;
+   wfRx[SDA].baud = bbBaud;
+
+   wfRx[SDA].I.started = 0;
+   wfRx[SDA].I.SDA = SDA;
+   wfRx[SDA].I.SCL = SCL;
+   wfRx[SDA].I.delay = 500000 / bbBaud;
+   wfRx[SDA].I.SDAMode = gpioGetMode(SDA);
+   wfRx[SDA].I.SCLMode = gpioGetMode(SCL);
+
+   wfRx[SCL].gpio = SCL;
+   wfRx[SCL].mode = PI_WFRX_I2C_CLK;
+
+   myGpioSetMode(SDA, PI_INPUT);
+   myGpioSetMode(SCL, PI_INPUT);
+
+   return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+
+int bbI2CClose(unsigned SDA)
+{
+   DBG(DBG_USER, "SDA=%d", SDA);
+
+   CHECK_INITED;
+
+   if (SDA > PI_MAX_USER_GPIO)
+      SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", SDA);
+
+   switch(wfRx[SDA].mode)
+   {
+      case PI_WFRX_I2C:
+
+         gpioSetMode(wfRx[SDA].I.SDA, wfRx[SDA].I.SDAMode);
+         gpioSetMode(wfRx[SDA].I.SCL, wfRx[SDA].I.SCLMode);
+
+         wfRx[wfRx[SDA].I.SDA].mode = PI_WFRX_NONE;
+         wfRx[wfRx[SDA].I.SCL].mode = PI_WFRX_NONE;
+
+         break;
+
+      default:
+
+         SOFT_ERROR(PI_NOT_I2C_GPIO, "no I2C on gpio (%d)", SDA);
+
+         break;
+
+   }
+
+   return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+int bbI2CXfer(
+   unsigned SDA,
+   char *inBuf, unsigned inLen, char *outBuf, unsigned outLen)
+{
+   int i, ack, inPos, outPos, status, bytes, len_bytes;
+   wfRx_t *w;
+
+   DBG(DBG_USER, "gpio=%d inBuf=%s outBuf=%08X len=%d",
+      SDA, myBuf2Str(inLen, (char *)inBuf), (int)outBuf, outLen);
+
+   CHECK_INITED;
+
+   if (SDA > PI_MAX_USER_GPIO)
+      SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", SDA);
+
+   if (wfRx[SDA].mode != PI_WFRX_I2C)
+      SOFT_ERROR(PI_NOT_I2C_GPIO, "no I2C on gpio (%d)", SDA);
+
+   if (!inBuf || !inLen)
+      SOFT_ERROR(PI_BAD_POINTER, "input buffer can't be NULL");
+
+   if (!outBuf && outLen)
+      SOFT_ERROR(PI_BAD_POINTER, "output buffer can't be NULL");
+
+   w = &wfRx[SDA];
+
+   inPos = 0;
+   outPos = 0;
+   status = 0;
+
+   while (!status && (inPos < inLen))
+   {
+      DBG(DBG_INTERNAL, "status=%d inpos=%d inlen=%d cmd=%d",
+         status, inPos, inLen, inBuf[inPos]);
+
+      len_bytes = 1;
+
+      switch (inBuf[inPos++])
+      {
+         case PI_I2C_END:
+            status = 1;
+            break;
+
+         case PI_I2C_START:
+            I2CStart(w);
+            break;
+
+         case PI_I2C_STOP:
+            I2CStop(w);
+            break;
+
+         case PI_I2C_READ16:
+            len_bytes = 2;
+            /* fall through */
+
+         case PI_I2C_READ:
+            if (inPos <= (inLen - len_bytes))
+            {
+               if (len_bytes != 1)
+               {
+                  bytes=inBuf[inPos] + (inBuf[inPos+1]<<8);
+                  inPos += 2;
+               }
+               else
+               {
+                  bytes=inBuf[inPos++];
+               }
+
+               if (bytes && ((bytes + outPos) < outLen))
+               {
+                  for (i=0; i<(bytes-1); i++)
+                  {
+                     outBuf[outPos++] = I2CGetByte(w, 0);
+                  }
+                  outBuf[outPos++] = I2CGetByte(w, 1);
+               }
+               else status = PI_BAD_BB_WLEN;
+            }
+            else status = PI_BAD_BB_WLEN;
+            break;
+
+         case PI_I2C_WRITE16:
+            len_bytes = 2;
+            /* fall through */
+
+         case PI_I2C_WRITE:
+            if (inPos <= (inLen - len_bytes))
+            {
+               if (len_bytes != 1)
+               {
+                  bytes=inBuf[inPos] + (inBuf[inPos+1]<<8);
+                  inPos += 2;
+               }
+               else
+               {
+                  bytes=inBuf[inPos++];
+               }
+
+               if (bytes && ((bytes + inPos) < inLen))
+               {
+                  for (i=0; i<(bytes-1); i++)
+                  {
+                     ack = I2CPutByte(w, inBuf[inPos++]);
+                     if (ack) status = PI_I2C_WRITE_FAILED;
+                  }
+                  ack = I2CPutByte(w, inBuf[inPos++]);
+                  //if (ack) status = PI_I2C_WRITE_FAILED;
+               }
+               else status = PI_BAD_BB_RLEN;
+            }
+            else status = PI_BAD_BB_RLEN;
+            break;
+
+         default:
+            status = PI_BAD_BB_CMD;
+      }
+   }
+
+   if (status >= 0) status = outPos;
+
+   return status;
+}
+
+
 /*-------------------------------------------------------------------------*/
 
 int gpioSerialReadOpen(unsigned gpio, unsigned bbBaud, unsigned bbBits)
@@ -8141,28 +8748,29 @@ int gpioSerialReadOpen(unsigned gpio, unsigned bbBaud, unsigned bbBits)
    if (wfRx[gpio].mode != PI_WFRX_NONE)
       SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used", gpio);
 
-   bitTime = (1000 * MILLION) / bbBaud; /* nanoseconds */
+   bitTime = (1000 * MILLION) / bbBaud; /* nanos */
 
-   timeout  = ((bbBits+2) * bitTime)/MILLION; /* milliseconds */
+   timeout  = ((bbBits+2) * bitTime)/MILLION; /* millis */
 
    if (timeout < 1) timeout = 1;
 
-   wfRx[gpio].gpio     = gpio;
-   wfRx[gpio].buf      = malloc(SRX_BUF_SIZE);
-   wfRx[gpio].bufSize  = SRX_BUF_SIZE;
-   wfRx[gpio].mode     = PI_WFRX_SERIAL;
-   wfRx[gpio].baud     = bbBaud;
-   wfRx[gpio].timeout  = timeout;
-   wfRx[gpio].fullBit  = bitTime;         /* nanoseconds */
-   wfRx[gpio].halfBit  = (bitTime/2)+500; /* nanoseconds (500 for rounding) */
-   wfRx[gpio].readPos  = 0;
-   wfRx[gpio].writePos = 0;
-   wfRx[gpio].bit      = -1;
-   wfRx[gpio].dataBits = bbBits;
-
-   if      (bbBits <  9) wfRx[gpio].bytes = 1;
-   else if (bbBits < 17) wfRx[gpio].bytes = 2;
-   else                  wfRx[gpio].bytes = 4;
+   wfRx[gpio].gpio = gpio;
+   wfRx[gpio].mode = PI_WFRX_SERIAL;
+   wfRx[gpio].baud = bbBaud;
+
+   wfRx[gpio].s.buf      = malloc(SRX_BUF_SIZE);
+   wfRx[gpio].s.bufSize  = SRX_BUF_SIZE;
+   wfRx[gpio].s.timeout  = timeout;
+   wfRx[gpio].s.fullBit  = bitTime;         /* nanos */
+   wfRx[gpio].s.halfBit  = (bitTime/2)+500; /* nanos (500 for rounding) */
+   wfRx[gpio].s.readPos  = 0;
+   wfRx[gpio].s.writePos = 0;
+   wfRx[gpio].s.bit      = -1;
+   wfRx[gpio].s.dataBits = bbBits;
+
+   if      (bbBits <  9) wfRx[gpio].s.bytes = 1;
+   else if (bbBits < 17) wfRx[gpio].s.bytes = 2;
+   else                  wfRx[gpio].s.bytes = 4;
 
    gpioSetAlertFunc(gpio, waveRxBit);
 
@@ -8174,7 +8782,7 @@ int gpioSerialReadOpen(unsigned gpio, unsigned bbBaud, unsigned bbBits)
 int gpioSerialRead(unsigned gpio, void *buf, size_t bufSize)
 {
    unsigned bytes=0, wpos;
-   volatile wfRx_t *p;
+   volatile wfRx_t *w;
 
    DBG(DBG_USER, "gpio=%d buf=%08X bufSize=%d", gpio, (int)buf, bufSize);
 
@@ -8189,26 +8797,26 @@ int gpioSerialRead(unsigned gpio, void *buf, size_t bufSize)
    if (wfRx[gpio].mode != PI_WFRX_SERIAL)
       SOFT_ERROR(PI_NOT_SERIAL_GPIO, "no serial read on gpio (%d)", gpio);
 
-   p = &wfRx[gpio];
+   w = &wfRx[gpio];
 
-   if (p->readPos != p->writePos)
+   if (w->s.readPos != w->s.writePos)
    {
-      wpos = p->writePos;
+      wpos = w->s.writePos;
 
-      if (wpos > p->readPos) bytes = wpos - p->readPos;
-      else                   bytes = p->bufSize - p->readPos;
+      if (wpos > w->s.readPos) bytes = wpos - w->s.readPos;
+      else                     bytes = w->s.bufSize - w->s.readPos;
 
       if (bytes > bufSize) bytes = bufSize;
 
       /* copy in multiples of the data size in bytes */
 
-      bytes = (bytes / p->bytes) * p->bytes;
+      bytes = (bytes / w->s.bytes) * w->s.bytes;
 
-      if (buf) memcpy(buf, p->buf+p->readPos, bytes);
+      if (buf) memcpy(buf, w->s.buf+w->s.readPos, bytes);
 
-      p->readPos += bytes;
+      w->s.readPos += bytes;
 
-      if (p->readPos >= p->bufSize) p->readPos = 0;
+      if (w->s.readPos >= w->s.bufSize) w->s.readPos = 0;
    }
    return bytes;
 }
@@ -8235,7 +8843,7 @@ int gpioSerialReadClose(unsigned gpio)
 
       case PI_WFRX_SERIAL:
 
-         free(wfRx[gpio].buf);
+         free(wfRx[gpio].s.buf);
 
          gpioSetWatchdog(gpio, 0); /* switch off timeouts */
 
@@ -8357,6 +8965,7 @@ int gpioNotifyOpen(void)
    gpioNotify[slot].bits  = 0;
    gpioNotify[slot].fd    = fd;
    gpioNotify[slot].pipe  = 1;
+   gpioNotify[slot].lastReportTick = gpioTick();
 
    return slot;
 }
@@ -8390,6 +8999,7 @@ static int gpioNotifyOpenInBand(int fd)
    gpioNotify[slot].bits  = 0;
    gpioNotify[slot].fd    = fd;
    gpioNotify[slot].pipe  = 0;
+   gpioNotify[slot].lastReportTick = gpioTick();
 
    return slot;
 }
@@ -9368,9 +9978,10 @@ uint32_t gpioDelay(uint32_t micros)
 
    start = systReg[SYST_CLO];
 
-   if (micros <= PI_MAX_BUSY_DELAY) while ((systReg[SYST_CLO] - start) <= micros);
-
-   else gpioSleep(PI_TIME_RELATIVE, (micros/MILLION), (micros%MILLION));
+   if (micros <= PI_MAX_BUSY_DELAY)
+      while ((systReg[SYST_CLO] - start) <= micros);
+   else
+      gpioSleep(PI_TIME_RELATIVE, (micros/MILLION), (micros%MILLION));
 
    return (systReg[SYST_CLO] - start);
 }
@@ -9663,3 +10274,4 @@ int gpioCfgInternals(unsigned cfgWhat, int cfgVal)
 /* include any user customisations */
 
 #include "custom.cext"
+
index 69afbc83249c9ba3d6509dd88d9d936f55e826e5..d5c302d7996f9e6c00c4d2db25772046c9ea2062 100644 (file)
--- a/pigpio.h
+++ b/pigpio.h
@@ -31,7 +31,7 @@ For more information, please refer to <http://unlicense.org/>
 #include <stdint.h>
 #include <pthread.h>
 
-#define PIGPIO_VERSION 31
+#define PIGPIO_VERSION 3202
 
 /*TEXT
 
@@ -225,20 +225,20 @@ i2cClose                   Closes an I2C device
 i2cReadDevice              Reads the raw I2C device
 i2cWriteDevice             Writes the raw I2C device
 
-i2cWriteQuick              smbus write quick
-i2cWriteByte               smbus write byte
-i2cReadByte                smbus read byte
-i2cWriteByteData           smbus write byte data
-i2cWriteWordData           smbus write word data
-i2cReadByteData            smbus read byte data
-i2cReadWordData            smbus read word data
-i2cProcessCall             smbus process call
-i2cWriteBlockData          smbus write block data
-i2cReadBlockData           smbus read block data
-i2cBlockProcessCall        smbus block process call
-
-i2cWriteI2CBlockData       smbus write I2C block data
-i2cReadI2CBlockData        smbus read I2C block data
+i2cWriteQuick              SMBus write quick
+i2cWriteByte               SMBus write byte
+i2cReadByte                SMBus read byte
+i2cWriteByteData           SMBus write byte data
+i2cWriteWordData           SMBus write word data
+i2cReadByteData            SMBus read byte data
+i2cReadWordData            SMBus read word data
+i2cProcessCall             SMBus process call
+i2cWriteBlockData          SMBus write block data
+i2cReadBlockData           SMBus read block data
+i2cBlockProcessCall        SMBus block process call
+
+i2cWriteI2CBlockData       SMBus write I2C block data
+i2cReadI2CBlockData        SMBus read I2C block data
 
 SPI
 
@@ -327,36 +327,36 @@ extern "C" {
 
 typedef struct
 {
-uint16_t func;
-uint16_t size;
+   uint16_t func;
+   uint16_t size;
 } gpioHeader_t;
 
 typedef struct
 {
-size_t size;
-void *ptr;
-uint32_t data;
+   size_t size;
+   void *ptr;
+   uint32_t data;
 } gpioExtent_t;
 
 typedef struct
 {
-uint32_t tick;
-uint32_t level;
+   uint32_t tick;
+   uint32_t level;
 } gpioSample_t;
 
 typedef struct
 {
-uint16_t seqno;
-uint16_t flags;
-uint32_t tick;
-uint32_t level;
+   uint16_t seqno;
+   uint16_t flags;
+   uint32_t tick;
+   uint32_t level;
 } gpioReport_t;
 
 typedef struct
 {
-uint32_t gpioOn;
-uint32_t gpioOff;
-uint32_t usDelay;
+   uint32_t gpioOn;
+   uint32_t gpioOff;
+   uint32_t usDelay;
 } gpioPulse_t;
 
 #define WAVE_FLAG_READ  1
@@ -365,10 +365,10 @@ uint32_t usDelay;
 
 typedef struct
 {
-uint32_t gpioOn;
-uint32_t gpioOff;
-uint32_t usDelay;
-uint32_t flags;
+   uint32_t gpioOn;
+   uint32_t gpioOff;
+   uint32_t usDelay;
+   uint32_t flags;
 } rawWave_t;
 
 typedef struct
@@ -381,41 +381,26 @@ typedef struct
 
 typedef struct
 {
-int clk;     /* gpio for clock           */
-int mosi;    /* gpio for MOSI            */
-int miso;    /* gpio for MISO            */
-int ss_pol;  /* slave select off state   */
-int ss_us;   /* delay after slave select */
-int clk_pol; /* clock off state          */
-int clk_pha; /* clock phase              */
-int clk_us;  /* clock micros             */
+   int clk;     /* gpio for clock           */
+   int mosi;    /* gpio for MOSI            */
+   int miso;    /* gpio for MISO            */
+   int ss_pol;  /* slave select off state   */
+   int ss_us;   /* delay after slave select */
+   int clk_pol; /* clock off state          */
+   int clk_pha; /* clock phase              */
+   int clk_us;  /* clock micros             */
 } rawSPI_t;
 
 typedef struct { /* linux/arch/arm/mach-bcm2708/include/mach/dma.h */
-uint32_t info;
-uint32_t src;
-uint32_t dst;
-uint32_t length;
-uint32_t stride;
-uint32_t next;
-uint32_t pad[2];
+   uint32_t info;
+   uint32_t src;
+   uint32_t dst;
+   uint32_t length;
+   uint32_t stride;
+   uint32_t next;
+   uint32_t pad[2];
 } rawCbs_t;
 
-/* max pi_i2c_msg_t per transaction */
-
-#define  PI_I2C_RDRW_IOCTL_MAX_MSGS 42
-
-/* flags for pi_i2c_msg_t */
-
-#define PI_I2C_M_WR           0x0000 /* write data */
-#define PI_I2C_M_RD           0x0001 /* read data */
-#define PI_I2C_M_TEN          0x0010 /* ten bit chip address */
-#define PI_I2C_M_RECV_LEN     0x0400 /* length will be first received byte */
-#define PI_I2C_M_NO_RD_ACK    0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define PI_I2C_M_IGNORE_NAK   0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define PI_I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define PI_I2C_M_NOSTART      0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
-
 typedef struct
 {
    uint16_t addr;  /* slave address       */
@@ -521,6 +506,7 @@ typedef void *(gpioThreadFunc_t) (void *);
 
 #define PI_NOTIFY_SLOTS  32
 
+#define PI_NTFY_FLAGS_ALIVE    (1 <<6)
 #define PI_NTFY_FLAGS_WDOG     (1 <<5)
 #define PI_NTFY_FLAGS_BIT(x) (((x)<<0)&31)
 
@@ -564,6 +550,43 @@ typedef void *(gpioThreadFunc_t) (void *);
 #define PI_MAX_I2C_DEVICE_COUNT (1<<16)
 #define PI_MAX_SPI_DEVICE_COUNT (1<<16)
 
+/* max pi_i2c_msg_t per transaction */
+
+#define  PI_I2C_RDRW_IOCTL_MAX_MSGS 42
+
+/* flags for pi_i2c_msg_t */
+
+#define PI_I2C_M_WR           0x0000 /* write data */
+#define PI_I2C_M_RD           0x0001 /* read data */
+#define PI_I2C_M_TEN          0x0010 /* ten bit chip address */
+#define PI_I2C_M_RECV_LEN     0x0400 /* length will be first received byte */
+#define PI_I2C_M_NO_RD_ACK    0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_IGNORE_NAK   0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_NOSTART      0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+
+/* bit bang I2C commands */
+
+#define PI_I2C_END     0
+#define PI_I2C_START   1
+#define PI_I2C_STOP    2
+#define PI_I2C_READ    3
+#define PI_I2C_WRITE   4
+#define PI_I2C_READ16  5
+#define PI_I2C_WRITE16 6
+
+/* combined transaction I2C flag commands */
+
+#define PI_I2C_F_CLEAR        40 /* clear flags */
+#define PI_I2C_F_TEN          41 /* ten bit chip address */
+#define PI_I2C_F_RECV_LEN     42 /* length will be first received byte */
+#define PI_I2C_F_NO_RD_ACK    43 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_F_IGNORE_NAK   44 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_F_REV_DIR_ADDR 45 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_F_NOSTART      46 /* if I2C_FUNC_PROTOCOL_MANGLING */
+
+/* SPI */
+
 #define PI_SPI_FLAGS_BITLEN(x) ((x&63)<<16)
 #define PI_SPI_FLAGS_RX_LSB(x)  ((x&1)<<15)
 #define PI_SPI_FLAGS_TX_LSB(x)  ((x&1)<<14)
@@ -1740,7 +1763,7 @@ 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
+For the SMBus commands the low level transactions are shown at the end
 of the function description.  The following abbreviations are used.
 
 . .
@@ -1821,7 +1844,7 @@ 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.
 
-Quick command. smbus 2.0 5.5.1
+Quick command. SMBus 2.0 5.5.1
 . .
 S Addr Rd/Wr [A] P
 . .
@@ -1841,7 +1864,7 @@ 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.
 
-Send byte. smbus 2.0 5.5.2
+Send byte. SMBus 2.0 5.5.2
 . .
 S Addr Wr [A] Data [A] P
 . .
@@ -1860,7 +1883,7 @@ handle: >=0, as returned by a call to [*i2cOpen*]
 Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE,
 or PI_I2C_READ_FAILED.
 
-Receive byte. smbus 2.0 5.5.3
+Receive byte. SMBus 2.0 5.5.3
 . .
 S Addr Rd [A] [Data] NA P
 . .
@@ -1882,7 +1905,7 @@ i2cReg: 0-255, the register 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
+Write byte. SMBus 2.0 5.5.4
 . .
 S Addr Wr [A] Comm [A] Data [A] P
 . .
@@ -1904,7 +1927,7 @@ i2cReg: 0-255, the register 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
+Write word. SMBus 2.0 5.5.4
 . .
 S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
 . .
@@ -1925,7 +1948,7 @@ i2cReg: 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
+Read byte. SMBus 2.0 5.5.5
 . .
 S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
 . .
@@ -1946,7 +1969,7 @@ i2cReg: 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
+Read word. SMBus 2.0 5.5.5
 . .
 S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
 . .
@@ -1968,7 +1991,7 @@ i2cReg: 0-255, the register to write/read
 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
+Process call. SMBus 2.0 5.5.6
 . .
 S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
    S Addr Rd [A] [DataLow] A [DataHigh] NA P
@@ -1993,7 +2016,7 @@ i2cReg: 0-255, the register 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
+Block write. SMBus 2.0 5.5.7
 . .
 S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
 . .
@@ -2017,7 +2040,7 @@ 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
+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
@@ -2043,11 +2066,11 @@ i2cReg: 0-255, the register to write/read
 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
+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
+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
@@ -2101,6 +2124,14 @@ S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
 . .
 D*/
 
+int bbI2COpen(unsigned SDA, unsigned SCL, unsigned bbBaud);
+
+int bbI2CClose(unsigned SDA);
+
+int bbI2CXfer(
+   unsigned SDA,
+   char *inBuf, unsigned inLen, char *outBuf, unsigned outLen);
+
 
 /*F*/
 int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags);
@@ -4252,6 +4283,12 @@ PARAMS*/
 #define PI_CMD_CF1   87
 #define PI_CMD_CF2   88
 
+#define PI_CMD_BI2CC 89
+#define PI_CMD_BI2CO 90
+#define PI_CMD_BI2CX 91
+
+#define PI_CMD_I2CX  92
+
 #define PI_CMD_NOIB  99
 
 /*DEF_E*/
@@ -4354,7 +4391,7 @@ after this command is issued.
 #define PI_BAD_WAVE_BAUD    -35 // baud rate not 50-250K(RX)/50-1M(TX)
 #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_NOT_SERIAL_GPIO  -38 // no bit bang 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_NOT_PERMITTED    -41 // gpio operation not permitted
@@ -4423,7 +4460,11 @@ after this command is issued.
 #define PI_BAD_MALLOC_MODE -104 // bad memory allocation mode
 #define PI_TOO_MANY_PARTS  -105 // too many I2C transaction parts
 #define PI_BAD_I2C_PART    -106 // a combined I2C transaction failed
-
+#define PI_BAD_SMBUS_CMD   -107 // SMBus command not supported by driver
+#define PI_NOT_I2C_GPIO    -108 // no bit bang I2C in progress on gpio
+#define PI_BAD_BB_WLEN     -109 // bad BB write length
+#define PI_BAD_BB_RLEN     -110 // bad BB read length
+#define PI_BAD_BB_CMD      -111 // bad BB command
 
 #define PI_PIGIF_ERR_0    -2000
 #define PI_PIGIF_ERR_99   -2099
@@ -4448,7 +4489,7 @@ after this command is issued.
 #define PI_DEFAULT_UPDATE_MASK_R0        0xFFFFFFFF
 #define PI_DEFAULT_UPDATE_MASK_R1        0x03E7CF93
 #define PI_DEFAULT_UPDATE_MASK_R2        0xFBC7CF9C
-#define PI_DEFAULT_UPDATE_MASK_R3        0x0080400FFFFFFCLL
+#define PI_DEFAULT_UPDATE_MASK_R3        0x0080480FFFFFFCLL
 #define PI_DEFAULT_UPDATE_MASK_COMPUTE   0x00FFFFFFFFFFFFLL
 #define PI_DEFAULT_MEM_ALLOC_MODE        PI_MEM_ALLOC_AUTO
 
index 42518fcf9fc02322b42a6307b23b3c7af95437e4..cc43e582d42a5270b3709513854efa9bbdb3083e 100644 (file)
--- a/pigpio.py
+++ b/pigpio.py
@@ -197,20 +197,20 @@ i2c_close                 Closes an I2C device
 i2c_read_device           Reads the raw I2C device
 i2c_write_device          Writes the raw 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_read_i2c_block_data   smbus read I2C block data
-i2c_write_i2c_block_data  smbus write I2C block data
+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_read_i2c_block_data   SMBus read I2C block data
+i2c_write_i2c_block_data  SMBus write I2C block data
 
 SPI
 
@@ -257,7 +257,7 @@ import threading
 import os
 import atexit
 
-VERSION = "1.16"
+VERSION = "1.17"
 
 exceptions = True
 
@@ -304,6 +304,12 @@ PI_SCRIPT_RUNNING=2
 PI_SCRIPT_WAITING=3
 PI_SCRIPT_FAILED =4
 
+# notification flags
+
+NTFY_FLAGS_ALIVE = (1 << 6)
+NTFY_FLAGS_WDOG  = (1 << 5)
+NTFY_FLAGS_GPIO  = 31
+
 # pigpio command numbers
 
 _PI_CMD_MODES= 0
@@ -519,6 +525,10 @@ PI_BAD_DATABITS     =-101
 PI_BAD_STOPBITS     =-102
 PI_MSG_TOOBIG       =-103
 PI_BAD_MALLOC_MODE  =-104
+_PI_TOO_MANY_PARTS  =-105
+_PI_BAD_I2C_PART    =-106
+PI_BAD_SMBUS_CMD    =-107
+PI_NOT_I2C_GPIO     =-108
 
 # pigpio error text
 
@@ -560,7 +570,7 @@ _errors=[
    [PI_BAD_WAVE_BAUD     , "baud rate not 50-250000(RX)/1000000(TX)"],
    [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_NOT_SERIAL_GPIO   , "no bit bang serial read in progress on gpio"],
    [PI_NOT_PERMITTED     , "no permission to update gpio"],
    [PI_SOME_PERMITTED    , "no permission to update one or more gpios"],
    [PI_BAD_WVSC_COMMND   , "bad WVSC subcommand"],
@@ -625,6 +635,10 @@ _errors=[
    [PI_BAD_STOPBITS      , "serial (half) stop bits not 2-8"],
    [PI_MSG_TOOBIG        , "socket/pipe message too big"],
    [PI_BAD_MALLOC_MODE   , "bad memory allocation mode"],
+   [_PI_TOO_MANY_PARTS    , "too many I2C transaction parts"],
+   [_PI_BAD_I2C_PART      , "a combined I2C transaction failed"],
+   [PI_BAD_SMBUS_CMD     , "SMBus command not supported"],
+   [PI_NOT_I2C_GPIO      , "no bit bang I2C in progress on gpio"],
 
 ]
 
@@ -867,10 +881,11 @@ class _callback_thread(threading.Thread):
                      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)
+               if flags & NTFY_FLAGS_WDOG:
+                  gpio = flags & NTFY_FLAGS_GPIO
+                  for cb in self.callbacks:
+                     if cb.gpio == gpio:
+                        cb.func(cb.gpio, TIMEOUT, tick)
 
       self.sl.s.close()
 
@@ -1993,7 +2008,7 @@ class pi():
 
       Normally you would only use the [*i2c_**] functions if
       you are or will be connecting to the Pi over a network.  If
-      you will always run on the local Pi use the standard smbus
+      you will always run on the local Pi use the standard SMBus
       module instead.
 
       ...
@@ -2080,7 +2095,7 @@ class pi():
       """
       Sends a single bit to the device associated with handle.
 
-      smbus 2.0 5.5.1 - Quick command.
+      SMBus 2.0 5.5.1 - Quick command.
 
       handle:= >=0 (as returned by a prior call to [*i2c_open*]).
          bit:= 0 or 1, the value to write.
@@ -2096,7 +2111,7 @@ class pi():
       """
       Sends a single byte to the device associated with handle.
 
-      smbus 2.0 5.5.2 - Send byte.
+      SMBus 2.0 5.5.2 - Send byte.
 
         handle:= >=0 (as returned by a prior call to [*i2c_open*]).
       byte_val:= 0-255, the value to write.
@@ -2113,7 +2128,7 @@ class pi():
       """
       Reads a single byte from the device associated with handle.
 
-      smbus 2.0 5.5.3 - Receive byte.
+      SMBus 2.0 5.5.3 - Receive byte.
 
       handle:= >=0 (as returned by a prior call to [*i2c_open*]).
 
@@ -2128,7 +2143,7 @@ class pi():
       Writes a single byte to the specified register of the device
       associated with handle.
 
-      smbus 2.0 5.5.4 - Write byte.
+      SMBus 2.0 5.5.4 - Write byte.
 
         handle:= >=0 (as returned by a prior call to [*i2c_open*]).
            reg:= >=0, the device register.
@@ -2156,7 +2171,7 @@ class pi():
       Writes a single 16 bit word to the specified register of the
       device associated with handle.
 
-      smbus 2.0 5.5.4 - Write word.
+      SMBus 2.0 5.5.4 - Write word.
 
         handle:= >=0 (as returned by a prior call to [*i2c_open*]).
            reg:= >=0, the device register.
@@ -2184,7 +2199,7 @@ class pi():
       Reads a single byte from the specified register of the device
       associated with handle.
 
-      smbus 2.0 5.5.5 - Read byte.
+      SMBus 2.0 5.5.5 - Read byte.
 
       handle:= >=0 (as returned by a prior call to [*i2c_open*]).
          reg:= >=0, the device register.
@@ -2204,7 +2219,7 @@ class pi():
       Reads a single 16 bit word from the specified register of the
       device associated with handle.
 
-      smbus 2.0 5.5.5 - Read word.
+      SMBus 2.0 5.5.5 - Read word.
 
       handle:= >=0 (as returned by a prior call to [*i2c_open*]).
          reg:= >=0, the device register.
@@ -2224,7 +2239,7 @@ class pi():
       Writes 16 bits of data to the specified register of the device
       associated with handle and reads 16 bits of data in return.
 
-      smbus 2.0 5.5.6 - Process call.
+      SMBus 2.0 5.5.6 - Process call.
 
         handle:= >=0 (as returned by a prior call to [*i2c_open*]).
            reg:= >=0, the device register.
@@ -2249,7 +2264,7 @@ class pi():
       Writes up to 32 bytes to the specified register of the device
       associated with handle.
 
-      smbus 2.0 5.5.7 - Block write.
+      SMBus 2.0 5.5.7 - Block write.
 
       handle:= >=0 (as returned by a prior call to [*i2c_open*]).
          reg:= >=0, the device register.
@@ -2281,7 +2296,7 @@ class pi():
       Reads a block of up to 32 bytes from the specified register of
       the device associated with handle.
 
-      smbus 2.0 5.5.7 - Block read.
+      SMBus 2.0 5.5.7 - Block read.
 
       handle:= >=0 (as returned by a prior call to [*i2c_open*]).
          reg:= >=0, the device register.
@@ -2316,13 +2331,13 @@ class pi():
       associated with handle and reads a device specified number
       of bytes of data in return.
 
-      smbus 2.0 5.5.8 - Block write-block read.
+      SMBus 2.0 5.5.8 - Block write-block read.
 
       handle:= >=0 (as returned by a prior call to [*i2c_open*]).
          reg:= >=0, the device register.
         data:= the bytes to write.
 
-      The smbus 2.0 documentation states that a minimum of 1 byte may
+      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.
 
diff --git a/pigs.c b/pigs.c
index e4e2421b65214519d27829e0ca3ac7d572ba2475..18691640d4d046bfb6e17360ef2b44f0a841b182 100644 (file)
--- a/pigs.c
+++ b/pigs.c
@@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
 */
 
 /*
-This version is for pigpio version 26+
+This version is for pigpio version 32+
 */
 
 #include <stdio.h>
@@ -141,7 +141,7 @@ void print_result(int sock, int rv, cmdCmd_t cmd)
          printf(cmdUsage);
          break;
 
-      case 6: /* CF2 I2CPK I2CRD I2CRI I2CRK SERR SLR SPIX SPIR */
+      case 6: /* BI2CX CF2 I2CPK I2CRD I2CRI I2CRK SERR SLR SPIX SPIR */
          printf("%d", r);
          if (r < 0) fatal("ERROR: %s", cmdErrStr(r));
          if (r > 0)
@@ -178,6 +178,7 @@ void get_extensions(int sock, int command, int res)
 {
    switch (command)
    {
+      case PI_CMD_BI2CX:
       case PI_CMD_CF2:
       case PI_CMD_I2CPK:
       case PI_CMD_I2CRD:
index 8fec0ac6a27df287643b3a62e84604e4639bc264..b027567813a39b6941744e9b1cdc7cb0134c4350 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
 from distutils.core import setup
 
 setup(name='pigpio',
-      version='1.16',
+      version='1.17',
       author='joan',
       author_email='joan@abyz.co.uk',
       maintainer='joan',