V26
authorjoan <joan@abyz.me.uk>
Mon, 2 Feb 2015 21:11:28 +0000 (21:11 +0000)
committerjoan <joan@abyz.me.uk>
Mon, 2 Feb 2015 21:11:28 +0000 (21:11 +0000)
Makefile
command.c
custom.cext [new file with mode: 0644]
pigpio.c
pigpio.h
pigpio.py
pigpiod_if.c
pigpiod_if.h
pigs.c
x_pigs
x_pipe

index d2811f60629ac8f497f857a30968b07a97fb6e5a..f7206a7a75d7a489e4fb3eaafd21b92f8d51254c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,4 @@
+#
 CC     = gcc
 AR      = ar
 RANLIB  = ranlib
@@ -80,12 +81,12 @@ $(LIB2):    $(OBJ2)
 
 # generated using gcc -MM *.c
 
-x_pigpio.o: x_pigpio.c pigpio.h
-x_pigpiod_if.o: x_pigpiod_if.c
 command.o: command.c pigpio.h command.h
 pig2vcd.o: pig2vcd.c pigpio.h
-pigpio.o: pigpio.c pigpio.h command.h
+pigpio.o: pigpio.c pigpio.h command.h custom.cext
 pigpiod.o: pigpiod.c pigpio.h
 pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h
 pigs.o: pigs.c pigpio.h command.h
+x_pigpio.o: x_pigpio.c pigpio.h
+x_pigpiod_if.o: x_pigpiod_if.c pigpiod_if.h pigpio.h
 
index e5a94a5c62c660f1307c387f5c4dbd97d2057c9e..53b807478ef85d92e55244a0ac94e41d553d24b6 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 25+
+This version is for pigpio version 26+
 */
 
 #include <stdio.h>
@@ -51,6 +51,9 @@ cmdInfo_t cmdInfo[]=
    {PI_CMD_BS1,   "BS1",   111, 1}, // gpioWrite_Bits_0_31_Set
    {PI_CMD_BS2,   "BS2",   111, 1}, // gpioWrite_Bits_32_53_Set
 
+   {PI_CMD_CF1,   "CF1",   195, 2}, // gpioCustom1
+   {PI_CMD_CF2,   "CF2",   195, 6}, // gpioCustom2
+
    {PI_CMD_GDC,   "GDC",   112, 2}, // gpioGetPWMdutycycle
    {PI_CMD_GPW,   "GPW",   112, 2}, // gpioGetServoPulsewidth
 
@@ -217,163 +220,167 @@ cmdInfo_t cmdInfo[]=
 
 
 char * cmdUsage = "\
-BC1 bits         Clear specified gpios in bank 1.\n\
-BC2 bits         Clear specified gpios in bank 2.\n\
-BR1              Read bank 1 gpios.\n\
-BR2              Read bank 2 gpios.\n\
-BS1 bits         Set specified gpios in bank 2.\n\
-BS2 bits         Set specified gpios in bank 2.\n\
+BC1 bits         Clear specified gpios in bank 1\n\
+BC2 bits         Clear specified gpios in bank 2\n\
+BR1              Read bank 1 gpios\n\
+BR2              Read bank 2 gpios\n\
+BS1 bits         Set specified gpios in bank 2\n\
+BS2 bits         Set specified gpios in bank 2\n\
+\n\
+CF1 uvs          Custom function 1\n\
+CF2 uvs          Custom function 2\n\
 \n\
-GDC u            Get PWM dutycycle for gpio.\n\
-GPW u            Get servo pulsewidth for gpio.\n\
+GDC u            Get PWM dutycycle for gpio\n\
+GPW u            Get servo pulsewidth for gpio\n\
 \n\
-H/HELP           Display command help.\n\
+H/HELP           Display command help\n\
 \n\
-HC g cf          Set hardware clock frequency.\n\
-HP g pf pdc      Set hardware PWM frequency and dutycycle.\n\
+HC g cf          Set hardware clock frequency\n\
+HP g pf pdc      Set hardware PWM frequency and dutycycle\n\
 \n\
-HWVER            Get hardware version.\n\
+HWVER            Get hardware version\n\
 \n\
-I2CC h           Close I2C handle.\n\
-I2CO ib id if    Open I2C bus and device with flags.\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     smb Process Call: exchange register with word\n\
+I2CPK h r bvs    smb Block Process Call: exchange data bytes with register\n\
 \n\
-I2CRB h r        smb 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\
+I2CRB h r        smb 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\
 \n\
-I2CWB h r bv     smb 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\
+I2CWB h r bv     smb 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\
 \n\
-M/MODES g m      Set gpio mode.\n\
-MG/MODEG g       Get gpio mode.\n\
+M/MODES g m      Set gpio mode\n\
+MG/MODEG g       Get gpio mode\n\
 \n\
-MICS v           Delay for microseconds.\n\
-MILS v           Delay for milliseconds.\n\
+MICS v           Delay for microseconds\n\
+MILS v           Delay for milliseconds\n\
 \n\
-NB h bits        Start notification.\n\
-NC h             Close notification.\n\
-NO               Request a notification.\n\
-NP h             Pause notification.\n\
+NB h bits        Start notification\n\
+NC h             Close notification\n\
+NO               Request a notification\n\
+NP h             Pause notification\n\
 \n\
-P/PWM u v        Set gpio PWM value.\n\
+P/PWM u v        Set gpio PWM value\n\
 \n\
-PARSE t          Validate script.\n\
+PARSE t          Validate script\n\
 \n\
-PFG u            Get gpio PWM frequency.\n\
-PFS u v          Set gpio PWM frequency.\n\
+PFG u            Get gpio PWM frequency\n\
+PFS u v          Set gpio PWM frequency\n\
 \n\
-PIGPV            Get pigpio library version.\n\
+PIGPV            Get pigpio library version\n\
 \n\
-PRG u            Get gpio PWM range.\n\
+PRG u            Get gpio PWM range\n\
 \n\
-PROC t           Store script.\n\
-PROCD sid        Delete script.\n\
-PROCP sid        Get script status and parameters.\n\
-PROCR sid pars   Run script.\n\
-PROCS sid        Stop script.\n\
+PROC t           Store script\n\
+PROCD sid        Delete script\n\
+PROCP sid        Get script status and parameters\n\
+PROCR sid pars   Run script\n\
+PROCS sid        Stop script\n\
 \n\
-PRRG u           Get gpio PWM real range.\n\
-PRS u v          Set gpio PWM range.\n\
+PRRG u           Get gpio PWM real range\n\
+PRS u v          Set gpio PWM range\n\
 \n\
-PUD g p          Set gpio pull up/down.\n\
+PUD g p          Set gpio pull up/down\n\
 \n\
-R/READ g         Read gpio level.\n\
+R/READ g         Read gpio level\n\
 \n\
-S/SERVO u v      Set gpio servo pulsewidth.\n\
+S/SERVO u v      Set gpio servo pulsewidth\n\
 \n\
-SERC h           Close serial handle.\n\
-SERDA h          Check for serial data ready to read.\n\
-SERO srd srb srf Open serial device at baud with flags.\n\
+SERC h           Close serial handle\n\
+SERDA h          Check for serial data ready to read\n\
+SERO srd srb srf Open serial device at baud with flags\n\
 \n\
-SERR h num       Read bytes from serial handle.\n\
-SERRB            Read byte from serial handle.\n\
-SERW h bvs       Write bytes to serial handle.\n\
-SERWB h bv       Write byte to serial handle.\n\
+SERR h num       Read bytes from serial handle\n\
+SERRB h          Read byte from serial handle\n\
+SERW h bvs       Write bytes to serial handle\n\
+SERWB h bv       Write byte to serial handle\n\
 \n\
-SLR u num        Read bit bang serial data from gpio.\n\
-SLRC u           Close gpio for bit bang serial data.\n\
-SLRO u b db      Open gpio for bit bang serial data.\n\
+SLR u num        Read bit bang serial data from gpio\n\
+SLRC u           Close gpio for bit bang serial data\n\
+SLRO u b db      Open gpio for bit bang serial data\n\
 \n\
-SPIC h           SPI close handle.\n\
-SPIO sc sb sf    SPI open channel at baud with flags.\n\
-SPIR h num       SPI read bytes from handle.\n\
-SPIW h bvs       SPI write bytes to handle.\n\
-SPIX h bvs       SPI transfer bytes to handle.\n\
+SPIC h           SPI close handle\n\
+SPIO sc sb sf    SPI open channel at baud with flags\n\
+SPIR h num       SPI read bytes from handle\n\
+SPIW h bvs       SPI write bytes to handle\n\
+SPIX h bvs       SPI transfer bytes to handle\n\
 \n\
-T/TICK           Get current tick.\n\
+T/TICK           Get current tick\n\
 \n\
-TRIG u pl L      Trigger level for micros on gpio.\n\
+TRIG u pl L      Trigger level for micros on gpio\n\
 \n\
-W/WRITE g L      Write level to gpio.\n\
+W/WRITE g L      Write level to gpio\n\
 \n\
-WDOG u v         Set millisecond watchdog on gpio.\n\
+WDOG u v         Set millisecond watchdog on gpio\n\
 \n\
-WVAG trips       Wave add generic pulses.\n\
+WVAG trips       Wave add generic pulses\n\
 WVAS u b db hb   Wave add serial data for gpio u at b baud, db databits,\n\
-     o bvs            hb (half)stopbits, offset o micros from wave start.\n\
-WVBSY            Check if wave busy.\n\
-WVCLR            Wave clear.\n\
-WVCRE            Create wave from added pulses.\n\
-WVDEL wid        Delete waves w and higher.\n\
-WVGO             Wave transmit (DEPRECATED).\n\
-WVGOR            Wave transmit repeatedly (DEPRECATED).\n\
-WVHLT            Wave stop.\n\
-WVNEW            Start a new empty wave.\n\
-WVSC ws          Wave get DMA control block stats.\n\
-WVSM ws          Wave get micros stats.\n\
-WVSP ws          Wave get pulses stats.\n\
-WVTX wid         Transmit wave as one-shot.\n\
-WVTXR wid        Transmit wave repeatedly.\n\
+     o bvs            hb (half)stopbits, offset o micros from wave start\n\
+WVBSY            Check if wave busy\n\
+WVCLR            Wave clear\n\
+WVCRE            Create wave from added pulses\n\
+WVDEL wid        Delete waves w and higher\n\
+WVGO             Wave transmit (DEPRECATED)\n\
+WVGOR            Wave transmit repeatedly (DEPRECATED)\n\
+WVHLT            Wave stop\n\
+WVNEW            Start a new empty wave\n\
+WVSC ws          Wave get DMA control block stats\n\
+WVSM ws          Wave get micros stats\n\
+WVSP ws          Wave get pulses stats\n\
+WVTX wid         Transmit wave as one-shot\n\
+WVTXR wid        Transmit wave repeatedly\n\
 \n\
-bits  = a mask where (1<<g) is set for each gpio g of interest.\n\
-bv    = byte value (0-255).\n\
-bvs   = one or more byte values (0-255).\n\
-cf    = hardware clock frequency (4689-25M).\n\
-db    = data bits (1-32).\n\
-g     = any gpio (0-53).\n\
-h     = handle (>=0).\n\
-hb    = (half) stop bits (2-8).\n\
-ib    = I2C bus (0-1).\n\
-id    = I2C device (0-127).\n\
-if    = I2C flags (0).\n\
-L     = level (0-1).\n\
-m     = mode (RW540123).\n\
-num   = number of bytes to read.\n\
-o     = offset (>=0).\n\
-p     = pud (ODU).\n\
-pars  = 0 to 10 parameters for script.\n\
-pdc   = hardware PWM dutycycle (0-1000).\n\
-pf    = hardware PWM frequency (5-250K).\n\
-pl    = pulse length (1-100).\n\
-r     = register.\n\
-sid   = script id (>=0).\n\
-sb    = SPI baud.\n\
-sc    = SPI channel (0-1).\n\
-sf    = SPI flags (0-3).\n\
-srd   = serial device (/dev/tty*).\n\
-srb   = serial baud rate.\n\
-srf   = serial flags (0).\n\
-t     = text.\n\
-trips = 1 or more triplets of gpios on, gpios off, delay.\n\
-u     = user gpio (0-31).\n\
-v     = value.\n\
-w     = wave id (>=0).\n\
-ws    = 0=now, 1=high, 2=max.\n\
-wv    = word value (0-65535).\n\
+bits  = a mask where (1<<g) is set for each gpio g of interest\n\
+bv    = byte value (0-255)\n\
+bvs   = one or more byte values (0-255)\n\
+cf    = hardware clock frequency (4689-25M)\n\
+db    = data bits (1-32)\n\
+g     = any gpio (0-53)\n\
+h     = handle (>=0)\n\
+hb    = (half) stop bits (2-8)\n\
+ib    = I2C bus (0-1)\n\
+id    = I2C device (0-127)\n\
+if    = I2C flags (0)\n\
+L     = level (0-1)\n\
+m     = mode (RW540123)\n\
+num   = number of bytes to read\n\
+o     = offset (>=0)\n\
+p     = pud (ODU)\n\
+pars  = 0 to 10 parameters for script\n\
+pdc   = hardware PWM dutycycle (0-5000)\n\
+pf    = hardware PWM frequency (5-50K)\n\
+pl    = pulse length (1-100)\n\
+r     = register\n\
+sid   = script id (>=0)\n\
+sb    = SPI baud\n\
+sc    = SPI channel (0-1)\n\
+sf    = SPI flags (0-3)\n\
+srd   = serial device (/dev/tty*)\n\
+srb   = serial baud rate\n\
+srf   = serial flags (0)\n\
+t     = text\n\
+trips = 1 or more triplets of gpios on, gpios off, delay\n\
+u     = user gpio (0-31)\n\
+uvs   = zero or more values >= 0, any after the first two must <= 255\n\
+v     = value\n\
+w     = wave id (>=0)\n\
+ws    = 0=now, 1=high, 2=max\n\
+wv    = word value (0-65535)\n\
 \n\
 Numbers may be entered as hex (prefix 0x), octal (prefix 0),\n\
-otherwise they are assumed to be decimal.\n\
+otherwise they are assumed to be decimal\n\
 ";
 
 typedef struct
@@ -479,8 +486,8 @@ static errInfo_t errInfo[]=
    {PI_NOT_SERVO_GPIO   , "gpio is not in use for servo pulses"},
    {PI_NOT_HCLK_GPIO    , "gpio has no hardware clock"},
    {PI_NOT_HPWM_GPIO    , "gpio has no hardware PWM"},
-   {PI_BAD_HPWM_FREQ    , "hardware PWM frequency not 5-250K"},
-   {PI_BAD_HPWM_DUTY    , "hardware PWM dutycycle not 0-1000"},
+   {PI_BAD_HPWM_FREQ    , "hardware PWM frequency not 5-50K"},
+   {PI_BAD_HPWM_DUTY    , "hardware PWM dutycycle not 0-5000"},
    {PI_BAD_HCLK_FREQ    , "hardware clock frequency not 4689-25M"},
    {PI_BAD_HCLK_PASS    , "need password to use hardware clock 1"},
    {PI_HPWM_ILLEGAL     , "illegal, PWM in use for main clock"},
@@ -940,6 +947,52 @@ int cmdParse(
 
          break;
 
+      case 195: /* CF1  CF2
+
+                   Zero or more parameters, first two >=0, rest 0-255.
+                */
+         valid = 1;
+
+         ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[1]);
+
+         if (ctl->opt[1] == CMD_NUMERIC)
+         {
+            if ((int)p[1] >= 0)
+            {
+               ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[2]);
+
+               if (ctl->opt[2] == CMD_NUMERIC)
+               {
+                  if ((int)p[2] >= 0)
+                  {
+                     pars = 0;
+                     p8 = ext;
+
+                     while (pars < CMD_MAX_PARAM)
+                     {
+                        ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
+                        if (to1 == CMD_NUMERIC)
+                        {
+                           if (((int)tp1>=0) && ((int)tp1<=255))
+                           {
+                              pars++;
+                              *p8++ = tp1;
+                           }
+                           else valid = 0;
+                        }
+                        else break;
+                     }
+
+                     p[3] = pars;
+                  }
+                  else valid = 0;
+               }
+            }
+            else valid = 0;
+         }
+
+         break;
+
       case 196: /* WVAS
 
                    gpio baud offset char...
diff --git a/custom.cext b/custom.cext
new file mode 100644 (file)
index 0000000..905884d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+This version is for pigpio version 26+
+
+If you want customised functions replace this file with your own
+definitions for gpioCustom1 and gpioCustom2.
+*/
+
+#include "pigpio.h"
+
+int gpioCustom1(unsigned arg1, unsigned arg2, char *argx, unsigned count)
+{
+   int i;
+   unsigned max;
+
+   DBG(DBG_USER, "arg1=%d arg2=%d count=%d [%s]",
+      arg1, arg2, count, myBuf2Str(count, argx));
+
+   CHECK_INITED;
+
+   /* for dummy just return max parameter */
+
+   if (arg1 > arg2) max = arg1; else max = arg2;
+
+   for (i=0; i<count; i++) if (argx[i] > max) max = argx[i];
+
+   return max;
+}
+
+
+int gpioCustom2(unsigned arg1, char *argx, unsigned count,
+                char *retBuf, unsigned retMax)
+{
+   int i, j, t;
+
+   DBG(DBG_USER, "arg1=%d count=%d [%s] retMax=%d",
+      arg1, count, myBuf2Str(count, argx), retMax);
+
+   CHECK_INITED;
+
+   /* for dummy just return argx reversed */
+
+   if (count > retMax) count = retMax;
+
+   for (i=0, j=count-1; i<=j; i++, j--)
+   {
+      /* t used as argx and retBuf may be the same buffer */
+      t = argx[i];
+      retBuf[i] = argx[j];
+      retBuf[j] = t;
+   }
+
+   return count;
+}
+
index d15fe2f1011054830cac6f10959e4402f1a48cb1..cabe56b072edff4b3e184786c64be998acd328bb 100644 (file)
--- a/pigpio.c
+++ b/pigpio.c
@@ -25,10 +25,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 For more information, please refer to <http://unlicense.org/>
 */
 
-/* pigpio version 25 */
+/* pigpio version 26 */
 
 #include <stdio.h>
 #include <string.h>
+#include <strings.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -39,7 +40,6 @@ For more information, please refer to <http://unlicense.org/>
 #include <termios.h>
 #include <signal.h>
 #include <errno.h>
-#include <string.h>
 #include <time.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
@@ -188,7 +188,6 @@ bit 0 READ_LAST_NOT_SET_ERROR
 
 #define BIT  (1<<(gpio&0x1F))
 
-
 #define CHECK_INITED                                               \
    do                                                              \
    {                                                               \
@@ -286,15 +285,18 @@ bit 0 READ_LAST_NOT_SET_ERROR
 
 #define DMA_BUS_ADR 0x40000000
 
-#define AUX_BASE   0x20215000
-#define CLK_BASE   0x20101000
-#define DMA_BASE   0x20007000
-#define DMA15_BASE 0x20E05000
-#define GPIO_BASE  0x20200000
-#define PCM_BASE   0x20203000
-#define PWM_BASE   0x2020C000
-#define SPI_BASE   0x20204000
-#define SYST_BASE  0x20003000
+static volatile unsigned int piModel = 1;
+static volatile unsigned int PI_PERI_BASE = 0x20000000;
+
+#define AUX_BASE   (PI_PERI_BASE + 0x00215000)
+#define CLK_BASE   (PI_PERI_BASE + 0x00101000)
+#define DMA_BASE   (PI_PERI_BASE + 0x00007000)
+#define DMA15_BASE (PI_PERI_BASE + 0x00E05000)
+#define GPIO_BASE  (PI_PERI_BASE + 0x00200000)
+#define PCM_BASE   (PI_PERI_BASE + 0x00203000)
+#define PWM_BASE   (PI_PERI_BASE + 0x0020C000)
+#define SPI_BASE   (PI_PERI_BASE + 0x00204000)
+#define SYST_BASE  (PI_PERI_BASE + 0x00003000)
 
 #define AUX_LEN   0xD8
 #define CLK_LEN   0xA8
@@ -1257,6 +1259,14 @@ static char *myBuf2Str(unsigned count, char *buf)
 
 /* ----------------------------------------------------------------------- */
 
+static void myGpioWrite(unsigned gpio, unsigned level)
+{
+   if (level == PI_OFF) *(gpioReg + GPCLR0 + BANK) = BIT;
+   else                 *(gpioReg + GPSET0 + BANK) = BIT;
+}
+
+/* ----------------------------------------------------------------------- */
+
 static void myGpioSleep(int seconds, int micros)
 {
    struct timespec ts, rem;
@@ -1441,6 +1451,18 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
          }
          break;
 
+      case PI_CMD_CF1:
+         res = gpioCustom1(p[1], p[2], buf, p[3]);
+         break;
+
+
+      case PI_CMD_CF2:
+         /* a couple of extra precautions for untruested code */
+         if (p[2] > bufSize) p[2] = bufSize;
+         res = gpioCustom2(p[1], buf, p[3], buf, p[2]);
+         if (res > p[2]) res = p[2];
+         break;
+
       case PI_CMD_GDC: res = gpioGetPWMdutycycle(p[1]); break;
 
       case PI_CMD_GPW: res = gpioGetServoPulsewidth(p[1]); break;
@@ -1640,7 +1662,8 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
          if (myPermit(p[1])) res = gpioServo(p[1], p[2]);
          else
          {
-            DBG(DBG_USER, "gpioServo: gpio %d, no permission to update", p[1]);
+            DBG(DBG_USER,
+               "gpioServo: gpio %d, no permission to update", p[1]);
             res = PI_NOT_PERMITTED;
          }
          break;
@@ -2072,7 +2095,7 @@ static void waveCbOPrint(int pos)
 
    p = rawWaveCBAdr(pos);
 
-   fprintf(stderr, "i=%lx s=%lx d=%lx len=%lx s=%lx nxt=%lx\n",
+   fprintf(stderr, "i=%x s=%x d=%x len=%x s=%x nxt=%x\n",
       p->info, p->src, p->dst, p->length, p->stride, p->next);
 }
 
@@ -2115,6 +2138,9 @@ static int errCBsOOL(int cb, int botOOL, int topOOL)
 
 /* ----------------------------------------------------------------------- */
 
+#define PI_WAVE_COUNT_BLOCKS 3
+#define PI_WAVE_COUNT_LENGTH 10
+
 static int wave2Cbs(unsigned wave_mode)
 {
    int botCB=waveOutBotCB, botOOL=waveOutBotOOL, topOOL=waveOutTopOOL;
@@ -2129,6 +2155,9 @@ static int wave2Cbs(unsigned wave_mode)
 
    rawWave_t * waves;
 
+   int b, baseCB;
+   uint32_t def_next;
+
    numWaves = wfc[wfcur];
    waves    = wf [wfcur];
 
@@ -2221,6 +2250,73 @@ static int wave2Cbs(unsigned wave_mode)
          p->next   = waveCbPOadr(botCB) | DMA_BUS_ADR;
       }
 
+      if (waves[i].flags & WAVE_FLAG_COUNT)
+      {
+         if ((status = errCBsOOL(botCB+1, botOOL, topOOL-1))) return status;
+
+         baseCB = botCB;
+
+         def_next = waveCbPOadr(baseCB+(3*PI_WAVE_COUNT_BLOCKS)) | DMA_BUS_ADR;
+
+         /* set up all the OOLs */
+         for (b=0; b < (PI_WAVE_COUNT_BLOCKS*(PI_WAVE_COUNT_LENGTH+1)); b++)
+            rawWaveSetIn(b, def_next);
+
+         for (b=0; b<PI_WAVE_COUNT_BLOCKS; b++)
+            rawWaveSetIn( (b*(PI_WAVE_COUNT_LENGTH+1))+1,
+               waveCbPOadr (baseCB+((b*PI_WAVE_COUNT_BLOCKS)+3)) | DMA_BUS_ADR);
+
+         rawWaveSetIn
+            (((PI_WAVE_COUNT_BLOCKS-1)*(PI_WAVE_COUNT_LENGTH+1))+7, 0);
+
+         for (b=0; b<PI_WAVE_COUNT_BLOCKS; b++)
+         {
+            /* copy BOTTOM to NEXT */
+
+            p = rawWaveCBAdr(botCB++);
+
+            p->info = NORMAL_DMA;
+
+            p->src = waveOOLPOadr
+               (topOOL-((b+1)*(PI_WAVE_COUNT_LENGTH+1))) | DMA_BUS_ADR;
+            p->dst = (waveCbPOadr(botCB+1) + 20) | DMA_BUS_ADR;
+
+            p->length = 4;
+            p->next   = waveCbPOadr(botCB) | DMA_BUS_ADR;
+
+            /* copy BOTTOM to TOP */
+
+            p = rawWaveCBAdr(botCB++);
+
+            p->info   = NORMAL_DMA;
+
+            p->src = waveOOLPOadr
+               (topOOL-((b+1)*(PI_WAVE_COUNT_LENGTH+1))) | DMA_BUS_ADR;
+            p->dst = waveOOLPOadr
+               (topOOL-(1+(b*(PI_WAVE_COUNT_LENGTH+1)))) | DMA_BUS_ADR;
+
+            p->length = 4;
+            p->next   = waveCbPOadr(botCB) | DMA_BUS_ADR;
+
+            /* shift all down one */
+
+            p = rawWaveCBAdr(botCB++);
+
+            p->info   = NORMAL_DMA|DMA_SRC_INC|DMA_DEST_INC;
+
+            p->src = waveOOLPOadr
+               (topOOL-(((b+1)*(PI_WAVE_COUNT_LENGTH+1))-1)) | DMA_BUS_ADR;
+            p->dst = waveOOLPOadr
+               (topOOL-(((b+1)*(PI_WAVE_COUNT_LENGTH+1))-0)) | DMA_BUS_ADR;
+
+            p->length = PI_WAVE_COUNT_LENGTH*4;
+            p->next   = waveCbPOadr
+               (baseCB+(3*PI_WAVE_COUNT_BLOCKS)) | DMA_BUS_ADR;
+         }
+
+         topOOL -= PI_WAVE_COUNT_BLOCKS * (PI_WAVE_COUNT_LENGTH+1);
+      }
+
       if (waves[i].usDelay)
       {
          if ((status = errCBsOOL(botCB+1, botOOL, topOOL))) return status;
@@ -2458,6 +2554,12 @@ int rawWaveAddGeneric(unsigned numIn1, rawWave_t *in1)
          --level;
       }
 
+      if (out[outPos].flags & WAVE_FLAG_COUNT)
+      {
+         cbs += (3*PI_WAVE_COUNT_BLOCKS);
+         level -= (PI_WAVE_COUNT_BLOCKS*(PI_WAVE_COUNT_LENGTH+1));
+      }
+
       outPos++;
 
       if (inPos1 >= numIn1) tNext1 = -1;
@@ -3083,102 +3185,7 @@ static unsigned old_mode_amosi;
 static uint32_t old_spi_cntl0;
 static uint32_t old_spi_cntl1;
 
-static void spiInit(uint32_t flags)
-{
-   int resvd;
-
-   resvd = PI_SPI_FLAGS_GET_RESVD(flags);
-
-   if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
-   {
-      /* enable module and access to registers */
-
-      auxReg[AUX_ENABLES] |= AUXENB_SPI1;
-
-      /* save original state */
-
-      old_mode_ace0  = gpioGetMode(PI_ASPI_CE0);
-      old_mode_ace1  = gpioGetMode(PI_ASPI_CE1);
-      old_mode_ace2  = gpioGetMode(PI_ASPI_CE2);
-      old_mode_asclk = gpioGetMode(PI_ASPI_SCLK);
-      old_mode_amiso = gpioGetMode(PI_ASPI_MISO);
-      old_mode_amosi = gpioGetMode(PI_ASPI_MOSI);
-
-      old_spi_cntl0 = auxReg[AUX_SPI0_CNTL0_REG];
-      old_spi_cntl1 = auxReg[AUX_SPI0_CNTL1_REG];
-
-      /* set gpios to SPI mode */
-
-      if (!(resvd&1)) gpioSetMode(PI_ASPI_CE0,  PI_ALT4);
-      if (!(resvd&2)) gpioSetMode(PI_ASPI_CE1,  PI_ALT4);
-      if (!(resvd&4)) gpioSetMode(PI_ASPI_CE2,  PI_ALT4);
-
-      gpioSetMode(PI_ASPI_SCLK, PI_ALT4);
-      gpioSetMode(PI_ASPI_MISO, PI_ALT4);
-      gpioSetMode(PI_ASPI_MOSI, PI_ALT4);
-   }
-   else
-   {
-      /* save original state */
-
-      old_mode_ce0  = gpioGetMode(PI_SPI_CE0);
-      old_mode_ce1  = gpioGetMode(PI_SPI_CE1);
-      old_mode_sclk = gpioGetMode(PI_SPI_SCLK);
-      old_mode_miso = gpioGetMode(PI_SPI_MISO);
-      old_mode_mosi = gpioGetMode(PI_SPI_MOSI);
-
-      old_spi_cs  = spiReg[SPI_CS];
-      old_spi_clk = spiReg[SPI_CLK];
-
-      /* set gpios to SPI mode */
-
-      if (!(resvd&1)) gpioSetMode(PI_SPI_CE0,  PI_ALT0);
-      if (!(resvd&2)) gpioSetMode(PI_SPI_CE1,  PI_ALT0);
-
-      gpioSetMode(PI_SPI_SCLK, PI_ALT0);
-      gpioSetMode(PI_SPI_MISO, PI_ALT0);
-      gpioSetMode(PI_SPI_MOSI, PI_ALT0);
-   }
-}
-
-void spiTerm(uint32_t flags)
-{
-   int resvd;
-
-   resvd = PI_SPI_FLAGS_GET_RESVD(flags);
-
-   if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
-   {
-      /* restore original state */
-
-      if (!(resvd&1)) gpioSetMode(PI_ASPI_CE0,  old_mode_ace0);
-      if (!(resvd&2)) gpioSetMode(PI_ASPI_CE1,  old_mode_ace1);
-      if (!(resvd&4)) gpioSetMode(PI_ASPI_CE2,  old_mode_ace2);
-
-      gpioSetMode(PI_ASPI_SCLK, old_mode_asclk);
-      gpioSetMode(PI_ASPI_MISO, old_mode_amiso);
-      gpioSetMode(PI_ASPI_MOSI, old_mode_amosi);
-
-      auxReg[AUX_SPI0_CNTL0_REG] = old_spi_cntl0;
-      auxReg[AUX_SPI0_CNTL1_REG] = old_spi_cntl1;
-   }
-   else
-   {
-      /* restore original state */
-
-      if (!(resvd&1)) gpioSetMode(PI_SPI_CE0,  old_mode_ce0);
-      if (!(resvd&2)) gpioSetMode(PI_SPI_CE1,  old_mode_ce1);
-
-      gpioSetMode(PI_SPI_SCLK, old_mode_sclk);
-      gpioSetMode(PI_SPI_MISO, old_mode_miso);
-      gpioSetMode(PI_SPI_MOSI, old_mode_mosi);
-
-      spiReg[SPI_CS]  = old_spi_cs;
-      spiReg[SPI_CLK] = old_spi_clk;
-   }
-}
-
-uint32_t _spiTXBits(char *buf, int pos, int bitlen, int msbf)
+static uint32_t _spiTXBits(char *buf, int pos, int bitlen, int msbf)
 {
    uint32_t bits=0;
 
@@ -3194,7 +3201,8 @@ uint32_t _spiTXBits(char *buf, int pos, int bitlen, int msbf)
    return bits;
 }
 
-void _spiRXBits(char *buf, int pos, int bitlen, int msbf, uint32_t bits)
+static void _spiRXBits(
+   char *buf, int pos, int bitlen, int msbf, uint32_t bits)
 {
    if (buf)
    {
@@ -3206,18 +3214,30 @@ void _spiRXBits(char *buf, int pos, int bitlen, int msbf, uint32_t bits)
    }
 }
 
+static void spiACS(int channel, int on)
+{
+   int gpio;
 
-void spiGoA(
+   switch (channel)
+   {
+       case  0: gpio = PI_ASPI_CE0; break; 
+       case  1: gpio = PI_ASPI_CE1; break; 
+       default: gpio = PI_ASPI_CE2; break; 
+   }
+   myGpioWrite(gpio, on);
+}
+
+static void spiGoA(
    unsigned speed,    /* bits per second */
    uint32_t flags,    /* flags           */
    char     *txBuf,   /* tx buffer       */
    char     *rxBuf,   /* rx buffer       */
    unsigned count)    /* number of bytes */
 {
-   char bit_cs;
-   char bit_ir[4] = {1, 0, 1, 0};
-   char bit_or[4] = {0, 1, 0, 1};
-   char bit_ic[4] = {0, 0, 1, 1};
+   int cs;
+   char bit_ir[4] = {1, 0, 0, 1}; /* read on rising edge */
+   char bit_or[4] = {0, 1, 1, 0}; /* write on rising edge */
+   char bit_ic[4] = {0, 0, 1, 1}; /* invert clock */
 
    int mode, bitlen, txmsbf, rxmsbf, channel;
    unsigned txCnt=0;
@@ -3230,6 +3250,7 @@ void spiGoA(
    mode   =  PI_SPI_FLAGS_GET_MODE   (flags);
 
    bitlen =  PI_SPI_FLAGS_GET_BITLEN (flags);
+
    if (!bitlen) bitlen = 8;
 
    /* correct count for word size */
@@ -3240,23 +3261,35 @@ void spiGoA(
    txmsbf = !PI_SPI_FLAGS_GET_TX_LSB (flags);
    rxmsbf = !PI_SPI_FLAGS_GET_RX_LSB (flags);
 
-   bit_cs = ~PI_SPI_FLAGS_GET_CSPOLS(flags);
-   bit_cs = (1<<channel) ^ bit_cs;
-   bit_cs &= 7;
+   cs = PI_SPI_FLAGS_GET_CSPOLS(flags) & (1<<channel);
 
    spiDefaults = AUXSPI_CNTL0_SPEED(125000000/speed)   |
-                 AUXSPI_CNTL0_CS(bit_cs)               |
                  AUXSPI_CNTL0_IN_RISING(bit_ir[mode])  |
                  AUXSPI_CNTL0_OUT_RISING(bit_or[mode]) |
                  AUXSPI_CNTL0_INVERT_CLK(bit_ic[mode]) |
                  AUXSPI_CNTL0_MSB_FIRST(txmsbf)        |
                  AUXSPI_CNTL0_SHIFT_LEN(bitlen);
 
-   auxReg[AUX_SPI0_CNTL0_REG] = AUXSPI_CNTL0_ENABLE | AUXSPI_CNTL0_CLR_FIFOS;
+   if (!count)
+   {
+      auxReg[AUX_SPI0_CNTL0_REG] =
+         AUXSPI_CNTL0_ENABLE | AUXSPI_CNTL0_CLR_FIFOS;
+
+      usleep(10);
+
+      auxReg[AUX_SPI0_CNTL0_REG] = AUXSPI_CNTL0_ENABLE  | spiDefaults;
+
+      auxReg[AUX_SPI0_CNTL1_REG] = AUXSPI_CNTL1_MSB_FIRST(rxmsbf);
+
+      return;
+   }
+
+   auxReg[AUX_SPI0_CNTL0_REG] = AUXSPI_CNTL0_ENABLE  | spiDefaults;
 
-   auxReg[AUX_SPI0_CNTL0_REG] = AUXSPI_CNTL0_ENABLE | spiDefaults;
    auxReg[AUX_SPI0_CNTL1_REG] = AUXSPI_CNTL1_MSB_FIRST(rxmsbf);
 
+   spiACS(channel, cs);
+
    while ((txCnt < count) || (rxCnt < count))
    {
       statusReg = auxReg[AUX_SPI0_STAT_REG];
@@ -3269,7 +3302,8 @@ void spiGoA(
       {
          if (!rxEmpty)
          {
-            _spiRXBits(rxBuf, rxCnt++, bitlen, rxmsbf, auxReg[AUX_SPI0_IO_REG]);
+            _spiRXBits(
+               rxBuf, rxCnt++, bitlen, rxmsbf, auxReg[AUX_SPI0_IO_REG]);
          }
       }
 
@@ -3293,7 +3327,7 @@ void spiGoA(
 
    while ((auxReg[AUX_SPI0_STAT_REG] & AUXSPI_STAT_BUSY)) ;
 
-   auxReg[AUX_SPI0_CNTL0_REG] = spiDefaults; /* stop */
+   spiACS(channel, !cs);
 }
 
 static void spiGoS(
@@ -3322,6 +3356,10 @@ static void spiGoS(
                  SPI_CS_CSPOL(cspol)   |
                  SPI_CS_CLEAR(3);
 
+   spiReg[SPI_CS] = spiDefaults; /* stop */
+
+   if (!count) return;
+
    if (flag3w)
    {
       if (ren3w < count)
@@ -3401,10 +3439,17 @@ static void spiGo(
    char     *rxBuf,
    unsigned count)
 {
+   DBG(0, "spiGo");
    if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
+   {
+      DBG(0, "spiGoA");
       spiGoA(speed, flags, txBuf, rxBuf, count);
+   }
    else
+   {
+      DBG(0, "spiGoS");
       spiGoS(speed, flags, txBuf, rxBuf, count);
+   }
 }
 
 static int spiAnyOpen(uint32_t flags)
@@ -3422,6 +3467,122 @@ static int spiAnyOpen(uint32_t flags)
    return 0;
 }
 
+static void spiInit(uint32_t flags)
+{
+   uint32_t resvd, cspols;
+
+   resvd  = PI_SPI_FLAGS_GET_RESVD(flags);
+   cspols = PI_SPI_FLAGS_GET_CSPOLS(flags);
+
+   if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
+   {
+      /* enable module and access to registers */
+
+      auxReg[AUX_ENABLES] |= AUXENB_SPI1;
+
+      /* save original state */
+
+      old_mode_ace0  = gpioGetMode(PI_ASPI_CE0);
+      old_mode_ace1  = gpioGetMode(PI_ASPI_CE1);
+      old_mode_ace2  = gpioGetMode(PI_ASPI_CE2);
+      old_mode_asclk = gpioGetMode(PI_ASPI_SCLK);
+      old_mode_amiso = gpioGetMode(PI_ASPI_MISO);
+      old_mode_amosi = gpioGetMode(PI_ASPI_MOSI);
+
+      old_spi_cntl0 = auxReg[AUX_SPI0_CNTL0_REG];
+      old_spi_cntl1 = auxReg[AUX_SPI0_CNTL1_REG];
+
+      /* manually control auxiliary SPI chip selects */
+
+      if (!(resvd&1))
+      {
+         gpioSetMode(PI_ASPI_CE0,  PI_OUTPUT);
+         myGpioWrite(PI_ASPI_CE0, !(cspols&1));
+      }
+
+      if (!(resvd&2))
+      {
+         gpioSetMode(PI_ASPI_CE1,  PI_OUTPUT);
+         myGpioWrite(PI_ASPI_CE1, !(cspols&2));
+      }
+
+      if (!(resvd&4))
+      {
+         gpioSetMode(PI_ASPI_CE2,  PI_OUTPUT);
+         myGpioWrite(PI_ASPI_CE2, !(cspols&4));
+      }
+
+      /* set gpios to SPI mode */
+
+      gpioSetMode(PI_ASPI_SCLK, PI_ALT4);
+      gpioSetMode(PI_ASPI_MISO, PI_ALT4);
+      gpioSetMode(PI_ASPI_MOSI, PI_ALT4);
+   }
+   else
+   {
+      /* save original state */
+
+      old_mode_ce0  = gpioGetMode(PI_SPI_CE0);
+      old_mode_ce1  = gpioGetMode(PI_SPI_CE1);
+      old_mode_sclk = gpioGetMode(PI_SPI_SCLK);
+      old_mode_miso = gpioGetMode(PI_SPI_MISO);
+      old_mode_mosi = gpioGetMode(PI_SPI_MOSI);
+
+      old_spi_cs  = spiReg[SPI_CS];
+      old_spi_clk = spiReg[SPI_CLK];
+
+      /* set gpios to SPI mode */
+
+      if (!(resvd&1)) gpioSetMode(PI_SPI_CE0,  PI_ALT0);
+      if (!(resvd&2)) gpioSetMode(PI_SPI_CE1,  PI_ALT0);
+
+      gpioSetMode(PI_SPI_SCLK, PI_ALT0);
+      gpioSetMode(PI_SPI_MISO, PI_ALT0);
+      gpioSetMode(PI_SPI_MOSI, PI_ALT0);
+   }
+}
+
+void spiTerm(uint32_t flags)
+{
+   int resvd;
+
+   resvd = PI_SPI_FLAGS_GET_RESVD(flags);
+
+   if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
+   {
+      /* disable module and access to registers */
+
+      auxReg[AUX_ENABLES] &= (~AUXENB_SPI1);
+
+      /* restore original state */
+
+      if (!(resvd&1)) gpioSetMode(PI_ASPI_CE0,  old_mode_ace0);
+      if (!(resvd&2)) gpioSetMode(PI_ASPI_CE1,  old_mode_ace1);
+      if (!(resvd&4)) gpioSetMode(PI_ASPI_CE2,  old_mode_ace2);
+
+      gpioSetMode(PI_ASPI_SCLK, old_mode_asclk);
+      gpioSetMode(PI_ASPI_MISO, old_mode_amiso);
+      gpioSetMode(PI_ASPI_MOSI, old_mode_amosi);
+
+      auxReg[AUX_SPI0_CNTL0_REG] = old_spi_cntl0;
+      auxReg[AUX_SPI0_CNTL1_REG] = old_spi_cntl1;
+   }
+   else
+   {
+      /* restore original state */
+
+      if (!(resvd&1)) gpioSetMode(PI_SPI_CE0,  old_mode_ce0);
+      if (!(resvd&2)) gpioSetMode(PI_SPI_CE1,  old_mode_ce1);
+
+      gpioSetMode(PI_SPI_SCLK, old_mode_sclk);
+      gpioSetMode(PI_SPI_MISO, old_mode_miso);
+      gpioSetMode(PI_SPI_MOSI, old_mode_mosi);
+
+      spiReg[SPI_CS]  = old_spi_cs;
+      spiReg[SPI_CLK] = old_spi_clk;
+   }
+}
+
 int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)
 {
    int i, slot;
@@ -3434,7 +3595,7 @@ int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)
    if (PI_SPI_FLAGS_GET_AUX_SPI(spiFlags))
    {
       if (gpioHardwareRevision() < 16)
-         SOFT_ERROR(PI_NO_AUX_SPI, "no auxiliary SPI, need a B+");
+         SOFT_ERROR(PI_NO_AUX_SPI, "no auxiliary SPI, need a A+/B+");
 
       i = PI_NUM_AUX_SPI_CHANNEL;
    }
@@ -3450,7 +3611,11 @@ int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)
    if (spiFlags > (1<<22))
       SOFT_ERROR(PI_BAD_FLAGS, "bad spiFlags (0x%X)", spiFlags);
 
-   if (!spiAnyOpen(spiFlags)) spiInit(spiFlags); /* initialise on first open */
+   if (!spiAnyOpen(spiFlags)) /* initialise on first open */
+   {
+      spiInit(spiFlags);
+      spiGo(spiBaud, spiFlags, NULL, NULL, 0);
+   }
 
    slot = -1;
 
@@ -3506,7 +3671,7 @@ int spiRead(unsigned handle, char *buf, unsigned count)
    if (spiInfo[handle].state != PI_SPI_OPENED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
-   if ((count < 1) || (count > PI_MAX_SPI_DEVICE_COUNT))
+   if (count > PI_MAX_SPI_DEVICE_COUNT)
       SOFT_ERROR(PI_BAD_SPI_COUNT, "bad count (%d)", count);
 
    spiGo(spiInfo[handle].speed, spiInfo[handle].flags, NULL, buf, count);
@@ -3527,7 +3692,7 @@ int spiWrite(unsigned handle, char *buf, unsigned count)
    if (spiInfo[handle].state != PI_SPI_OPENED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
-   if ((count < 1) || (count > PI_MAX_SPI_DEVICE_COUNT))
+   if (count > PI_MAX_SPI_DEVICE_COUNT)
       SOFT_ERROR(PI_BAD_SPI_COUNT, "bad count (%d)", count);
 
    spiGo(spiInfo[handle].speed, spiInfo[handle].flags, buf, NULL, count);
@@ -3548,7 +3713,7 @@ int spiXfer(unsigned handle, char *txBuf, char *rxBuf, unsigned count)
    if (spiInfo[handle].state != PI_SPI_OPENED)
       SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
-   if ((count < 1) || (count > PI_MAX_SPI_DEVICE_COUNT))
+   if (count > PI_MAX_SPI_DEVICE_COUNT)
       SOFT_ERROR(PI_BAD_SPI_COUNT, "bad count (%d)", count);
 
    spiGo(spiInfo[handle].speed, spiInfo[handle].flags, txBuf, rxBuf, count);
@@ -3842,7 +4007,7 @@ static void dmaCbPrint(int pos)
 
    p = dmaCB2adr(pos);
 
-   fprintf(stderr, "i=%lx s=%lx d=%lx len=%lx s=%lx nxt=%lx\n",
+   fprintf(stderr, "i=%x s=%x d=%x len=%x s=%x nxt=%x\n",
       p->info, p->src, p->dst, p->length, p->stride, p->next);
 }
 
@@ -4153,43 +4318,30 @@ static void sigHandler(int signum)
       }
       else
       {
-         if (signum == SIGUSR1)
-         {
-            if (gpioCfg.dbgLevel > DBG_MIN_LEVEL)
-            {
-               --gpioCfg.dbgLevel;
-            }
-            else gpioCfg.dbgLevel = DBG_MIN_LEVEL;
-
-            DBG(DBG_USER, "Debug level %d\n", gpioCfg.dbgLevel);
-         }
-         else if (signum == SIGUSR2)
-         {
-            if (gpioCfg.dbgLevel < DBG_MAX_LEVEL)
-            {
-               ++gpioCfg.dbgLevel;
-            }
-            else gpioCfg.dbgLevel = DBG_MAX_LEVEL;
-
-            DBG(DBG_USER, "Debug level %d\n", gpioCfg.dbgLevel);
-         }
-         else if (signum == SIGPIPE)
-         {
-            /* can happen when pipe/socket is remote closed */
-            DBG(DBG_USER, "SIGPIPE received");
-         }
-         else if (signum == SIGCHLD)
+         switch(signum)
          {
-            /* happens when system call is made */
-            DBG(DBG_USER, "SIGCHLD received");
-         }
-         else
-         {
-            /* exit */
-
-            DBG(DBG_ALWAYS, "Unhandled signal %d, terminating\n", signum);
-
-            exit(-1);
+            case SIGUSR1:
+
+               if (gpioCfg.dbgLevel > DBG_MIN_LEVEL) --gpioCfg.dbgLevel;
+               else gpioCfg.dbgLevel = DBG_MIN_LEVEL;
+               DBG(DBG_USER, "Debug level %d\n", gpioCfg.dbgLevel);
+               break;
+
+            case SIGUSR2:
+               if (gpioCfg.dbgLevel < DBG_MAX_LEVEL) ++gpioCfg.dbgLevel;
+               else gpioCfg.dbgLevel = DBG_MAX_LEVEL;
+               DBG(DBG_USER, "Debug level %d\n", gpioCfg.dbgLevel);
+               break;
+
+            case SIGPIPE:
+            case SIGCHLD:
+            case SIGWINCH:
+               DBG(DBG_USER, "signal %d ignored", signum);
+               break;
+
+            default:
+               DBG(DBG_ALWAYS, "Unhandled signal %d, terminating\n", signum);
+               exit(-1);
          }
       }
    }
@@ -5177,6 +5329,7 @@ static void *pthSocketThreadHandler(void *fdC)
       {
          /* extensions */
 
+         case PI_CMD_CF2:
          case PI_CMD_I2CPK:
          case PI_CMD_I2CRD:
          case PI_CMD_I2CRI:
@@ -7090,7 +7243,8 @@ int rawWaveAddSPI(
    uint32_t on_bits, off_bits;
    int tx_bit_pos;
 
-   DBG(DBG_USER, "spi=%08X off=%d spiSS=%d tx=%08X, num=%d fb=%d lb=%d spiBits=%d",
+   DBG(DBG_USER,
+      "spi=%08X off=%d spiSS=%d tx=%08X, num=%d fb=%d lb=%d spiBits=%d",
       (uint32_t)spi, offset, spiSS, (uint32_t)buf, spiTxBits,
       spiBitFirst, spiBitLast, spiBits);
 
@@ -8561,7 +8715,11 @@ int gpioHardwarePWM(
       {
          /* record the PWM frequency and dutycycle */
 
-         hw_pwm_freq[pwm] = frequency / PI_HW_PWM_RANGE;
+         /* currently both channels must use the same update rate */
+
+         hw_pwm_freq[0] = frequency / PI_HW_PWM_RANGE;
+         hw_pwm_freq[1] = frequency / PI_HW_PWM_RANGE;
+
          hw_pwm_duty[pwm] = dutycycle;
 
          /* Abort any waveform transmission in progress */
@@ -8768,12 +8926,25 @@ unsigned gpioHardwareRevision(void)
    {
       while (fgets(buf, sizeof(buf), filp) != NULL)
       {
-         if (!strncasecmp("revision\t", buf, 9))
+         if (!strncmp("model name", buf, 10))
+         {
+            if (strstr (buf, "ARMv6") != NULL)
+            {
+               piModel = 1;
+               PI_PERI_BASE = 0x20000000;
+            }
+            else if (strstr (buf, "ARMv7") != NULL)
+            {
+               piModel = 2;
+               PI_PERI_BASE = 0x3F000000;
+            }
+         }
+
+         if (!strncmp("Revision", buf, 8))
          {
             if (sscanf(buf+strlen(buf)-5, "%x%c", &rev, &term) == 2)
             {
-               if (term == '\n') break;
-               rev = 0;
+               if (term != '\n') rev = 0;
             }
          }
       }
@@ -8897,7 +9068,6 @@ int gpioCfgInterfaces(unsigned ifFlags)
    return 0;
 }
 
-
 /* ----------------------------------------------------------------------- */
 
 int gpioCfgSocketPort(unsigned port)
@@ -8968,3 +9138,7 @@ int gpioCfgInternals(unsigned cfgWhat, int cfgVal)
    return retVal;
 }
 
+/* include any user customisations */
+
+#include "custom.cext"
+
index 3f8edb804a91e68375ffdafb933ab1052e8c7542..3c2d456f442db6593d5fdacaea7e46854d442faf 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 25
+#define PIGPIO_VERSION 26
 
 /*TEXT
 
@@ -351,8 +351,9 @@ uint32_t gpioOff;
 uint32_t usDelay;
 } gpioPulse_t;
 
-#define WAVE_FLAG_READ 1
-#define WAVE_FLAG_TICK 2
+#define WAVE_FLAG_READ  1
+#define WAVE_FLAG_TICK  2
+#define WAVE_FLAG_COUNT 4
 
 typedef struct
 {
@@ -383,13 +384,13 @@ int clk_us;  /* clock micros             */
 } rawSPI_t;
 
 typedef struct { /* linux/arch/arm/mach-bcm2708/include/mach/dma.h */
-unsigned long info;
-unsigned long src;
-unsigned long dst;
-unsigned long length;
-unsigned long stride;
-unsigned long next;
-unsigned long 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;
 
 typedef void (*gpioAlertFunc_t)    (int      gpio,
@@ -479,8 +480,8 @@ typedef void *(gpioThreadFunc_t) (void *);
 /* hardware PWM */
 
 #define PI_HW_PWM_MIN_FREQ 5
-#define PI_HW_PWM_MAX_FREQ 250000
-#define PI_HW_PWM_RANGE 1000
+#define PI_HW_PWM_MAX_FREQ 50000
+#define PI_HW_PWM_RANGE 5000
 
 /* hardware clock */
 
@@ -2083,8 +2084,8 @@ handle: >=0, as returned by a call to [*spiOpen*]
  count: the number of bytes to read
 . .
 
-Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
-PI_SPI_XFER_FAILED.
+Returns the number of bytes transferred if OK, otherwise
+PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
 D*/
 
 
@@ -2100,8 +2101,8 @@ handle: >=0, as returned by a call to [*spiOpen*]
  count: the number of bytes to write
 . .
 
-Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
-PI_SPI_XFER_FAILED.
+Returns the number of bytes transferred if OK, otherwise
+PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
 D*/
 
 /*F*/
@@ -2118,8 +2119,8 @@ handle: >=0, as returned by a call to [*spiOpen*]
  count: the number of bytes to transfer
 . .
 
-Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
-PI_SPI_XFER_FAILED.
+Returns the number of bytes transferred if OK, otherwise
+PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
 D*/
 
 
@@ -3052,6 +3053,48 @@ Or in PI_DISABLE_SOCK_IF to disable the socket interface.
 D*/
 
 
+/*F*/
+int gpioCustom1(unsigned arg1, unsigned arg2, char *argx, unsigned count);
+/*D
+This function is available for user customisation.
+
+It returns a single integer value.
+
+. .
+ arg1: >=0
+ arg2: >=0
+ argx: extra (byte) arguments
+count: number of extra arguments
+. .
+
+Returns >= 0 if OK, less than 0 indicates a user defined error.
+D*/
+
+
+/*F*/
+int gpioCustom2(unsigned arg1, char *argx, unsigned count,
+                char *retBuf, unsigned retMax);
+/*D
+This function is available for user customisation.
+
+It differs from gpioCustom1 in that it returns an array of bytes
+rather than just an integer.
+
+The returned value is an integer indicating the number of returned bytes.
+. .
+  arg1: >=0
+  argx: extra (byte) arguments
+ count: number of extra arguments
+retBuf: buffer for returned bytes
+retMax: maximum number of bytes to return
+. .
+
+Returns >= 0 if OK, less than 0 indicates a user defined error.
+
+The number of returned bytes must be retMax or less.
+D*/
+
+
 /*F*/
 int gpioCfgInternals(unsigned cfgWhat, int cfgVal);
 /*D
@@ -3686,7 +3729,7 @@ PWMduty::0-1000
 The hardware PWM dutycycle.
 
 . .
-#define PI_HW_PWM_RANGE 1000
+#define PI_HW_PWM_RANGE 5000
 . .
 
 PWMfreq::5-250K
@@ -3694,7 +3737,7 @@ The hardware PWM frequency.
 
 . .
 #define PI_HW_PWM_MIN_FREQ 5
-#define PI_HW_PWM_MAX_FREQ 250000
+#define PI_HW_PWM_MAX_FREQ 50000
 . .
 
 range::25-40000
@@ -4013,6 +4056,9 @@ PARAMS*/
 #define PI_CMD_HC    85
 #define PI_CMD_HP    86
 
+#define PI_CMD_CF1   87
+#define PI_CMD_CF2   88
+
 #define PI_CMD_NOIB  99
 
 /*DEF_E*/
@@ -4173,13 +4219,20 @@ after this command is issued.
 #define PI_NOT_SERVO_GPIO   -93 // gpio is not in use for servo pulses
 #define PI_NOT_HCLK_GPIO    -94 // gpio has no hardware clock
 #define PI_NOT_HPWM_GPIO    -95 // gpio has no hardware PWM
-#define PI_BAD_HPWM_FREQ    -96 // hardware PWM frequency not 5-250K
-#define PI_BAD_HPWM_DUTY    -97 // hardware PWM dutycycle not 0-1000
+#define PI_BAD_HPWM_FREQ    -96 // hardware PWM frequency not 5-50K
+#define PI_BAD_HPWM_DUTY    -97 // hardware PWM dutycycle not 0-5000
 #define PI_BAD_HCLK_FREQ    -98 // hardware clock frequency not 4689-25M
 #define PI_BAD_HCLK_PASS    -99 // need password to use hardware clock 1
 #define PI_HPWM_ILLEGAL    -100 // illegal, PWM in use for main clock
 #define PI_BAD_DATABITS    -101 // serial data bits not 1-32
 #define PI_BAD_STOPBITS    -102 // serial (half) stop bits not 2-8
+#define PI_MSG_TOOBIG      -103 // socket/pipe message too big
+
+#define PI_PIGIF_ERR_0    -2000
+#define PI_PIGIF_ERR_99   -2099
+
+#define PI_CUSTOM_ERR_0   -3000
+#define PI_CUSTOM_ERR_999 -3999
 
 /*DEF_E*/
 
index 5ca345f48a9914f556aebb9be607ae808ec5b7fe..a4f206199450c7933c0b7a01a3a89fd6889ec870 100644 (file)
--- a/pigpio.py
+++ b/pigpio.py
@@ -234,6 +234,11 @@ serial_write_byte         Writes a byte to a serial device
 
 serial_data_available     Returns number of bytes ready to be read
 
+CUSTOM
+
+custom_1                  User custom function 1
+custom_2                  User custom function 2
+
 Utility
 
 get_current_tick          Get current tick (microseconds)
@@ -402,6 +407,9 @@ _PI_CMD_GPW  =84
 _PI_CMD_HC   =85
 _PI_CMD_HP   =86
 
+_PI_CMD_CF1  =87
+_PI_CMD_CF2  =88
+
 _PI_CMD_NOIB= 99
 
 # pigpio error numbers
@@ -606,8 +614,8 @@ _errors=[
    [PI_NOT_SERVO_GPIO    , "gpio is not in use for servo pulses"],
    [PI_NOT_HCLK_GPIO     , "gpio has no hardware clock"],
    [PI_NOT_HPWM_GPIO     , "gpio has no hardware PWM"],
-   [PI_BAD_HPWM_FREQ     , "hardware PWM frequency not 5-250K"],
-   [PI_BAD_HPWM_DUTY     , "hardware PWM dutycycle not 0-1000"],
+   [PI_BAD_HPWM_FREQ     , "hardware PWM frequency not 5-50K"],
+   [PI_BAD_HPWM_DUTY     , "hardware PWM dutycycle not 0-5000"],
    [PI_BAD_HCLK_FREQ     , "hardware clock frequency not 4689-25M"],
    [PI_BAD_HCLK_PASS     , "need password to use hardware clock 1"],
    [PI_HPWM_ILLEGAL      , "illegal, PWM in use for main clock"],
@@ -1486,8 +1494,8 @@ class pi():
       pigpio daemon is started (option -t).
 
          gpio:= see descripton
-      PWMfreq:= 0 (off) or 5-250K
-      PWMduty:= 0 (off) to 1000 (fully on).
+      PWMfreq:= 0 (off) or 5-50K
+      PWMduty:= 0 (off) to 5000 (fully on).
 
       Returns 0 if OK, otherwise PI_NOT_PERMITTED, PI_BAD_GPIO,
       PI_NOT_HPWM_GPIO, PI_BAD_HPWM_DUTY, PI_BAD_HPWM_FREQ.
@@ -1514,9 +1522,9 @@ class pi():
       . .
 
       ...
-      pi.hardware_PWM(18, 800, 250) # 800Hz 25% dutycycle
+      pi.hardware_PWM(18, 800, 1250) # 800Hz 25% dutycycle
 
-      pi.hardware_PWM(18, 2000, 750) # 2000Hz 75% dutycycle
+      pi.hardware_PWM(18, 2000, 3750) # 2000Hz 75% dutycycle
       ...
       """
       # pigpio message format
@@ -2953,6 +2961,81 @@ class pi():
       """
       return _u2i(_pigpio_command(self.sl, _PI_CMD_SLRC, user_gpio, 0))
 
+   def custom_1(self, arg1=0, arg2=0, argx=[]):
+      """
+      Calls a pigpio function customised by the user.
+
+      arg1:= >=0, default 0.
+      arg2:= >=0, default 0.
+      argx:= extra arguments (each 0-255), default empty.
+
+      The returned value is an integer which by convention
+      should be >=0 for OK and <0 for error.
+
+      ...
+      value = pi.custom_1()
+
+      value = pi.custom_1(23)
+
+      value = pi.custom_1(0, 55)
+
+      value = pi.custom_1(23, 56, [1, 5, 7])
+
+      value = pi.custom_1(23, 56, b"hello")
+
+      value = pi.custom_1(23, 56, "hello")
+      ...
+      """
+      # I p1 arg1
+      # I p2 arg2
+      # I p3 len
+      ## extension ##
+      # s len argx bytes
+
+      return u2i(_pigpio_command_ext(
+         self.sl, _PI_CMD_CF1, arg1, arg2, len(argx), [argx]))
+
+   def custom_2(self, arg1=0, argx=[], retMax=8192):
+      """
+      Calls a pigpio function customised by the user.
+
+        arg1:= >=0, default 0.
+        argx:= extra arguments (each 0-255), default empty.
+      retMax:= >=0, maximum number of bytes to return, default 8192.
+
+      The returned value is a tuple of the number of bytes
+      returned and a bytearray containing the bytes.  If
+      there was an error the number of bytes read will be
+      less than zero (and will contain the error code).
+
+      ...
+      (count, data) = pi.custom_2()
+
+      (count, data) = pi.custom_2(23)
+
+      (count, data) = pi.custom_2(23, [1, 5, 7])
+
+      (count, data) = pi.custom_2(23, b"hello")
+
+      (count, data) = pi.custom_2(23, "hello", 128)
+      ...
+      """
+      # I p1 arg1
+      # I p2 retMax
+      # I p3 len
+      ## extension ##
+      # s len argx bytes
+
+      # Don't raise exception.  Must release lock.
+      bytes = u2i(_pigpio_command_ext(
+         self.sl, _PI_CMD_CF2, arg1, retMax, len(argx), [argx], False))
+      if bytes > 0:
+         data = self._rxbuf(bytes)
+      else:
+         data = ""
+      self.sl.l.release()
+      return bytes, data
+
    def callback(self, user_gpio, edge=RISING_EDGE, func=None):
       """
       Calls a user supplied function (a callback) whenever the
@@ -3043,9 +3126,6 @@ class pi():
       self.sl = _socklock()
       self._notify  = None
 
-      self._host = ''
-      self._port = 8888
-
       self._host = host
       self._port = int(port)
 
index c51e6a5fa74b8249f11f446be21d7d6d848c0a5e..95866b276bd3d40ae19ff7cf867013cac56ea052 100644 (file)
@@ -1313,6 +1313,58 @@ int serial_read(unsigned handle, char *buf, unsigned count)
 int serial_data_available(unsigned handle)
    {return pigpio_command(gPigCommand, PI_CMD_SERDA, handle, 0, 1);}
 
+int custom_1(unsigned arg1, unsigned arg2, char *argx, unsigned count)
+{
+   gpioExtent_t ext[1];
+
+   /*
+   p1=arg1
+   p2=arg2
+   p3=count
+   ## extension ##
+   char argx[count]
+   */
+
+   ext[0].size = count;
+   ext[0].ptr = argx;
+
+   return pigpio_command_ext(
+      gPigCommand, PI_CMD_CF1, arg1, arg2, count, 1, ext, 1);
+}
+
+
+int custom_2(unsigned arg1, char *argx, unsigned count,
+             char *retBuf, uint32_t retMax)
+{
+   int bytes;
+   gpioExtent_t ext[1];
+
+   /*
+   p1=arg1
+   p2=retMax
+   p3=count
+   ## extension ##
+   char argx[count]
+   */
+
+   ext[0].size = count;
+   ext[0].ptr = argx;
+
+   bytes = pigpio_command_ext
+      (gPigCommand, PI_CMD_CF2, arg1, retMax, count, 1, ext, 0);
+
+   if (bytes > 0)
+   {
+      /* get the data */
+      recv(gPigCommand, retBuf, bytes, MSG_WAITALL);
+   }
+
+   pthread_mutex_unlock(&command_mutex);
+
+   return bytes;
+}
+
+
 int callback(unsigned user_gpio, unsigned edge, CBFunc_t f)
    {return intCallback(user_gpio, edge, f, 0, 0);}
 
index 61596fa857f7457704bbd540c91c145a97b19a2a..b256d4662d8461560d5b81160f9276feddb29d2f 100644 (file)
@@ -248,6 +248,11 @@ serial_read                Reads bytes from a serial device
 
 serial_data_available      Returns number of bytes ready to be read
 
+CUSTOM
+
+custom_1                   User custom function 1
+custom_2                   User custom function 2
+
 UTILITIES
 
 get_current_tick           Get current tick (microseconds)
@@ -896,8 +901,8 @@ daemon is started (option -t).
 
 . .
    gpio: see descripton
-PWMfreq: 0 (off) or 5-250K
-PWMduty: 0 (off) to 1000 (fully on).
+PWMfreq: 0 (off) or 5-50K
+PWMduty: 0 (off) to 5000 (fully on).
 . .
 
 Returns 0 if OK, otherwise PI_NOT_PERMITTED, PI_BAD_GPIO,
@@ -1804,8 +1809,8 @@ handle: >=0, as returned by a call to [*spi_open*].
  count: the number of bytes to read.
 . .
 
-Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
-PI_SPI_XFER_FAILED.
+Returns the number of bytes transferred if OK, otherwise
+PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
 D*/
 
 /*F*/
@@ -1820,8 +1825,8 @@ handle: >=0, as returned by a call to [*spi_open*].
  count: the number of bytes to write.
 . .
 
-Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
-PI_SPI_XFER_FAILED.
+Returns the number of bytes transferred if OK, otherwise
+PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
 D*/
 
 /*F*/
@@ -1838,8 +1843,8 @@ handle: >=0, as returned by a call to [*spi_open*].
  count: the number of bytes to transfer.
 . .
 
-Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
-PI_SPI_XFER_FAILED.
+Returns the number of bytes transferred if OK, otherwise
+PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
 D*/
 
 /*F*/
@@ -1944,6 +1949,48 @@ Returns the number of bytes of data available (>=0) if OK,
 otherwise PI_BAD_HANDLE.
 D*/
 
+/*F*/
+int custom_1(unsigned arg1, unsigned arg2, char *argx, unsigned count);
+/*D
+This function is available for user customisation.
+
+It returns a single integer value.
+
+. .
+ arg1: >=0
+ arg2: >=0
+ argx: extra (byte) arguments
+count: number of extra arguments
+. .
+
+Returns >= 0 if OK, less than 0 indicates a user defined error.
+D*/
+
+
+/*F*/
+int custom_2(unsigned arg1, char *argx, unsigned count,
+             char *retBuf, unsigned retMax);
+/*D
+This function is available for user customisation.
+
+It differs from custom_1 in that it returns an array of bytes
+rather than just an integer.
+
+The return value is an integer indicating the number of returned bytes.
+. .
+  arg1: >=0
+  argx: extra (byte) arguments
+ count: number of extra arguments
+retBuf: buffer for returned data
+retMax: maximum number of bytes to return
+. .
+
+Returns >= 0 if OK, less than 0 indicates a user defined error.
+
+Note, the number of returned bytes will be retMax or less.
+D*/
+
+
 /*F*/
 int callback(unsigned user_gpio, unsigned edge, CBFunc_t f);
 /*D
diff --git a/pigs.c b/pigs.c
index 23d9bfe515e228a3be4b74ff949b01735b177880..e4e2421b65214519d27829e0ca3ac7d572ba2475 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 18+
+This version is for pigpio version 26+
 */
 
 #include <stdio.h>
@@ -141,7 +141,7 @@ void print_result(int sock, int rv, cmdCmd_t cmd)
          printf(cmdUsage);
          break;
 
-      case 6: /* I2CPK I2CRD I2CRI I2CRK SERR SLR SPIX SPIR */
+      case 6: /* 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_CF2:
       case PI_CMD_I2CPK:
       case PI_CMD_I2CRD:
       case PI_CMD_I2CRI:
diff --git a/x_pigs b/x_pigs
index 34c0642a88736f214063b2840fb114f3583e4711..9753cca0b7eb512f862b27307c11af57a36bd594 100755 (executable)
--- a/x_pigs
+++ b/x_pigs
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-VERSION=25
+VERSION=26
 
 GPIO=4
 
@@ -46,7 +46,7 @@ s=$(pigs bs2 0)
 if [[ $s = "" ]]; then echo "BS2 ok"; else echo "BS2 fail ($s)"; fi
 
 s=$(pigs h)
-if [[ ${#s} = 5150 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
+if [[ ${#s} = 5167 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
 
 s=$(pigs hwver)
 if [[ $s -ne 0 ]]; then echo "HWVER ok"; else echo "HWVER fail ($s)"; fi
diff --git a/x_pipe b/x_pipe
index 744dee50de02f572dc3da4070181b1c480a80f34..ba5341c5849996e1f3fd7edc836a7d9a30740d4c 100755 (executable)
--- a/x_pipe
+++ b/x_pipe
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-VERSION=25
+VERSION=26
 
 GPIO=4
 
@@ -52,14 +52,14 @@ if [[ $s = 0 ]]; then echo "BS2 ok"; else echo "BS2 fail ($s)"; fi
 
 echo "h" >/dev/pigpio
 read -t 1 s </dev/pigout
-if [[ $s = "BC1 bits         Clear specified gpios in bank 1." ]]
+if [[ $s = "BC1 bits         Clear specified gpios in bank 1" ]]
 then echo "HELP-a ok"
 else echo "HELP-a fail ($s)"
 fi
 read -t 1 -N 9000 </dev/pigout # dump rest of help
 echo "help" >/dev/pigpio
 read -t 1 s </dev/pigout
-if [[ $s = "BC1 bits         Clear specified gpios in bank 1." ]]
+if [[ $s = "BC1 bits         Clear specified gpios in bank 1" ]]
 then echo "HELP-b ok"
 else echo "HELP-b fail ($s)"
 fi