V39
authorjoan <joan@abyz.co.uk>
Wed, 28 Oct 2015 11:06:53 +0000 (11:06 +0000)
committerjoan <joan@abyz.co.uk>
Wed, 28 Oct 2015 11:06:53 +0000 (11:06 +0000)
command.c
pigpio.3
pigpio.c
pigpio.h
pigpio.py
pigpiod_if.3
pigpiod_if.c
pigpiod_if.h
pigs.1
setup.py
x_pigs

index 4a8154372371a793394c7175ee84d7fe6d6bb941..49ac7c62c540d0a32a2af4fcb84020c348c759d3 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 38+
+This version is for pigpio version 39+
 */
 
 #include <stdio.h>
@@ -61,6 +61,9 @@ cmdInfo_t cmdInfo[]=
    {PI_CMD_CGI,   "CGI",   101, 4}, // gpioCfgGetInternals
    {PI_CMD_CSI,   "CSI",   111, 1}, // gpioCfgSetInternals
 
+   {PI_CMD_FG,    "FG",    121, 0}, // gpioGlitchFilter
+   {PI_CMD_FN,    "FN",    131, 0}, // gpioNoiseFilter
+
    {PI_CMD_GDC,   "GDC",   112, 2}, // gpioGetPWMdutycycle
    {PI_CMD_GPW,   "GPW",   112, 2}, // gpioGetServoPulsewidth
 
@@ -247,6 +250,9 @@ CF2 ...          Custom function 2\n\
 CGI              Configuration get internals\n\
 CSI v            Configuration set internals\n\
 \n\
+FG g steady      Set glitch filter on gpio\n\
+FN g steady active | Set noise filter on gpio\n\
+\n\
 GDC g            Get PWM dutycycle for gpio\n\
 GPW g            Get servo pulsewidth for gpio\n\
 \n\
@@ -479,6 +485,7 @@ static errInfo_t errInfo[]=
    {PI_BAD_EDGE         , "bad ISR edge, not 1, 1, or 2"},
    {PI_BAD_ISR_INIT     , "bad ISR initialisation"},
    {PI_BAD_FOREVER      , "loop forever must be last chain command"},
+   {PI_BAD_FILTER       , "bad filter parameter"},
 
 };
 
index 1cb5d7164755196b78c9ea82ab6e3e365e67a5e1..c06b3de593cd9b0f4a6bb2122fba1e1bf8eb6a22 100644 (file)
--- a/pigpio.3
+++ b/pigpio.3
@@ -3862,6 +3862,79 @@ gpioSetWatchdog(4, 5);
 
 .EE
 
+.IP "\fBint gpioNoiseFilter(unsigned user_gpio, unsigned steady, unsigned active)\fP"
+.IP "" 4
+Sets a noise filter on a gpio.
+
+.br
+
+.br
+Level changes on the gpio are ignored until a level which has
+been stable for \fBsteady\fP microseconds is detected.  Level changes
+on the gpio are then reported for \fBactive\fP microseconds after
+which the process repeats.
+
+.br
+
+.br
+
+.EX
+user_gpio: 0-31
+.br
+   steady: 0-300000
+.br
+   active: 0-1000000
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER.
+
+.br
+
+.br
+Note, level changes before and after the active period may
+be reported.  Your software must be designed to cope with
+such reports.
+
+.IP "\fBint gpioGlitchFilter(unsigned user_gpio, unsigned steady)\fP"
+.IP "" 4
+Sets a glitch filter on a gpio.
+
+.br
+
+.br
+Level changes on the gpio are not reported unless the level
+has been stable for at least \fBsteady\fP microseconds.  The
+level is then reported.  Level changes of less than \fBsteady\fP
+microseconds are ignored.
+
+.br
+
+.br
+
+.EX
+user_gpio: 0-31
+.br
+   steady: 0-300000
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER.
+
+.br
+
+.br
+Note, each (stable) edge will be timestamped \fBsteady\fP microseconds
+after it was first detected.
+
 .IP "\fBint gpioSetGetSamplesFunc(gpioGetSamplesFunc_t f, uint32_t bits)\fP"
 .IP "" 4
 Registers a function to be called (a callback) every millisecond
@@ -5620,6 +5693,19 @@ Not intended for general use.
 
 .br
 
+.IP "\fBactive\fP: 0-1000000" 0
+
+.br
+
+.br
+The number of microseconds level changes are reported for once
+a noise filter has been triggered (by \fBsteady\fP microseconds of
+a stable level).
+
+.br
+
+.br
+
 .IP "\fB*arg\fP" 0
 
 .br
@@ -7138,6 +7224,19 @@ The number of bits to transfer dring a raw SPI transaction
 
 .br
 
+.IP "\fBsteady\fP: 0-300000" 0
+
+.br
+
+.br
+The number of microseconds level changes must be stable for
+before reporting the level changed (\fBgpioGlitchFilter\fP) or triggering
+the active part of a noise filter (\fBgpioNoiseFilter\fP).
+
+.br
+
+.br
+
 .IP "\fBstop_bits\fP: 2-8" 0
 The number of (half) stop bits to be used when adding serial data
 to a waveform.
@@ -7591,6 +7690,12 @@ A 16-bit word value.
 #define PI_CMD_CSI   96
 .br
 
+.br
+#define PI_CMD_FG    97
+.br
+#define PI_CMD_FN    98
+.br
+
 .br
 #define PI_CMD_NOIB  99
 .br
@@ -7855,6 +7960,8 @@ A 16-bit word value.
 .br
 #define PI_BAD_FOREVER     -124 // loop forever must be last chain command
 .br
+#define PI_BAD_FILTER      -125 // bad filter parameter
+.br
 
 .br
 #define PI_PIGIF_ERR_0    -2000
index 191226a41ba22c22dadf6777436ab314eed57a00..3205f2c9dd6f0c69da95950a3e37bc19f718ecb4 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 38 */
+/* pigpio version 39 */
 
 /* include ------------------------------------------------------- */
 
@@ -734,7 +734,7 @@ Assumes two counters per block.  Each counter 4 * 16 (16^4=65536)
 
 #define PI_WF_MICROS   1
 
-#define DATUMS 2000
+#define DATUMS 4000
 
 #define DEFAULT_PWM_IDX 5
 
@@ -868,8 +868,17 @@ typedef struct
    callbk_t func;
    unsigned ex;
    void *userdata;
-   int timeout;
-   uint32_t tick;
+   uint32_t wdTick;
+   uint32_t fnTick;
+   uint32_t fnTick2;
+   uint32_t fnLBitV;
+   int wdSteadyUs;
+   int fnSteadyUs;
+   int fnActiveUs;
+   uint32_t fgTick;
+   uint32_t fgDebounceUs;
+   uint32_t fgRBitV;
+   uint32_t fgLBitV;
 } gpioAlert_t;
 
 typedef struct
@@ -1144,6 +1153,7 @@ static volatile uint32_t alertBits   = 0;
 static volatile uint32_t monitorBits = 0;
 static volatile uint32_t notifyBits  = 0;
 static volatile uint32_t scriptBits  = 0;
+static volatile uint32_t filterBits  = 0;
 
 static volatile int runState = PI_STARTING;
 
@@ -1734,6 +1744,15 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
 
       case PI_CMD_CSI: res = gpioCfgSetInternals(p[1]); break;
 
+      case PI_CMD_FG:
+         res = gpioGlitchFilter(p[1], p[2]);
+         break;
+
+      case PI_CMD_FN:
+         memcpy(&p[4], buf, 4);
+         res = gpioNoiseFilter(p[1], p[2], p[4]);
+         break;
+
       case PI_CMD_GDC: res = gpioGetPWMdutycycle(p[1]); break;
 
       case PI_CMD_GPW: res = gpioGetServoPulsewidth(p[1]); break;
@@ -4994,26 +5013,165 @@ static void sigSetHandler(void)
    }
 }
 
-unsigned alert_delays[]={
-   1000, 1068, 1145, 1235,
-   1339, 1463, 1613, 1796,
-   2027, 2326, 2727, 3297,
-   4167, 5660, 8823, 20000};
+unsigned alert_delays[]=
+{
+   1000, 1034, 1071, 1111, 1154, 1200, 1250, 1304,
+   1364, 1429, 1500, 1579, 1667, 1765, 1875, 2000
+};
 
 /* ======================================================================= */
 
+static void alertGlitchFilter(int numSamples)
+{
+   int i, j, diff;
+   uint32_t DebounceUs, Tick, RBitV, LBitV;
+   uint32_t bit, bitV;
+
+   if (!numSamples) return;
+
+   for (i=0; i<=PI_MAX_USER_GPIO; i++)
+   {
+      bit = (1<<i);
+
+      if (monitorBits & bit)
+      {
+         DebounceUs = gpioAlert[i].fgDebounceUs;
+
+         if (DebounceUs)
+         {
+            RBitV = gpioAlert[i].fgRBitV;
+            LBitV = gpioAlert[i].fgLBitV;
+            Tick = gpioAlert[i].fgTick;
+
+            for (j=0; j<numSamples; j++)
+            {
+               bitV = gpioSample[j].level & bit;
+
+               if (bitV ^ LBitV)
+               {
+                  /* Difference between level and last level.
+                     Restart debounce timer. */
+
+                  Tick = gpioSample[j].tick;
+                  LBitV = bitV;
+               }
+
+               if (bitV ^ RBitV)
+               {
+                  /* Difference between level and reported level. */
+
+                  diff = gpioSample[j].tick - Tick;
+                  if (diff >= DebounceUs)
+                  {
+                     /* Level steady for debounce period. */
+
+                     RBitV = bitV;
+                  }
+                  else
+                  {
+                     /* Keep reporting old level. */
+
+                     gpioSample[j].level ^= bit;
+                  }
+               }
+            }
+
+            gpioAlert[i].fgRBitV = RBitV;
+            gpioAlert[i].fgLBitV = LBitV;
+            gpioAlert[i].fgTick = Tick;
+         }
+      }
+   }
+}
+
+static void alertActivityFilter(int numSamples)
+{
+   int i, j, diff;
+   uint32_t LBitV;
+   uint32_t bit;
+   uint32_t firstTick, nowTick, lastTick;
+
+   if (!numSamples) return;
+
+   firstTick = gpioSample[0].tick;
+   lastTick = gpioSample[numSamples-1].tick;
+
+   for (i=0; i<=PI_MAX_USER_GPIO; i++)
+   {
+      bit = (1<<i);
+
+      if ((monitorBits & bit)  &&
+         (gpioAlert[i].wdSteadyUs || gpioAlert[i].fnSteadyUs))
+      {
+         if (gpioAlert[i].fnSteadyUs)
+         {
+            diff = firstTick - gpioAlert[i].fnTick2;
+
+            if (diff >= 0)
+            {
+               /* Stop reporting gpio changes */
+               filterBits |= bit;
+            }
+         }
+
+         LBitV = gpioAlert[i].fnLBitV;
+
+         for (j=0; j<numSamples; j++)
+         {
+            if ((gpioSample[j].level & bit) != LBitV)
+            {
+               nowTick = gpioSample[j].tick;
+
+               if (gpioAlert[i].fnSteadyUs)
+               {
+                  diff = nowTick - gpioAlert[i].fnTick;
+
+                  if (diff >= gpioAlert[i].fnSteadyUs)
+                  {
+                     /* Start reporting gpio changes */
+                     filterBits &= (~bit);
+                     gpioAlert[i].fnTick2 =
+                        nowTick + gpioAlert[i].fnActiveUs;
+                  }
+               }
+
+               LBitV = gpioSample[j].level & bit;
+
+               gpioAlert[i].fnTick = nowTick;
+               gpioAlert[i].wdTick = nowTick;
+            }
+         }
+
+         gpioAlert[i].fnLBitV = LBitV;
+
+         if (gpioAlert[i].fnSteadyUs)
+         {
+            diff = lastTick - gpioAlert[i].fnTick;
+
+            if (diff >= gpioAlert[i].fnSteadyUs)
+            {
+               /* Start reporting gpio changes */
+               filterBits &= (~bit);
+               gpioAlert[i].fnTick2 = lastTick + gpioAlert[i].fnActiveUs;
+            }
+         }
+      }
+   }
+}
+
 static void * pthAlertThread(void *x)
 {
    struct timespec req, rem;
    uint32_t oldLevel, newLevel, level, reportedLevel;
    uint32_t oldSlot,  newSlot;
-   uint32_t tick, expected, nowTick;
+   uint32_t stick, expected, nowTick;
    int32_t diff;
    int cycle, pulse;
    int emit, seqno, emitted;
    uint32_t changes, bits, changedBits, timeoutBits;
    int numSamples, d;
    int b, n, v;
+   int rp, wp;
    int err;
    int stopped;
    int delayTicks;
@@ -5039,10 +5197,10 @@ static void * pthAlertThread(void *x)
 
    moreToDo = 0;
 
-   tick = systReg[SYST_CLO];
+   stick = systReg[SYST_CLO];
 
    nextWakeTick =
-      tick + alert_delays[(gpioCfg.internals>>PI_CFG_ALERT_FREQ)&15];
+      stick + alert_delays[(gpioCfg.internals>>PI_CFG_ALERT_FREQ)&15];
 
    while (1)
    {
@@ -5054,25 +5212,22 @@ static void * pthAlertThread(void *x)
 
       oldLevel = reportedLevel & monitorBits;
 
+      /* Work through latest samples saving any level
+         changes of gpios of interest.
+      */
+
       while ((oldSlot != newSlot) && (numSamples < DATUMS))
       {
          level = myGetLevel(oldSlot++);
 
          newLevel = (level & monitorBits);
 
-         if (newLevel != oldLevel)
-         {
-            gpioSample[numSamples].tick  = tick;
-            gpioSample[numSamples].level = level;
-
-            changedBits |= (newLevel ^ oldLevel);
-
-            oldLevel = newLevel;
+         gpioSample[numSamples].tick  = stick;
+         gpioSample[numSamples].level = level;
 
-            numSamples++;
-         }
+         numSamples++;
 
-         tick += gpioCfg.clockMicros;
+         stick += gpioCfg.clockMicros;
 
          if (++pulse >= PULSE_PER_CYCLE)
          {
@@ -5084,11 +5239,11 @@ static void * pthAlertThread(void *x)
                oldSlot = 0;
             }
 
-            expected = tick;
+            expected = stick;
 
-            tick = myGetTick(cycle);
+            stick = myGetTick(cycle);
 
-            diff = tick - expected;
+            diff = stick - expected;
 
             diff += (TICKSLOTS/2);
 
@@ -5108,7 +5263,35 @@ static void * pthAlertThread(void *x)
 
       if (oldSlot == newSlot) moreToDo = 0; else moreToDo = 1;
 
-      /* should gpioGetSamples be called */
+      /* Apply glitch filter */
+
+      alertGlitchFilter(numSamples);
+
+      /* Compact samples */
+
+      wp = 0;
+
+      for (rp=0; rp<numSamples; rp++)
+      {
+         level = gpioSample[rp].level;
+
+         newLevel = (level & monitorBits);
+
+         if (newLevel != oldLevel)
+         {
+            gpioSample[wp].tick  = gpioSample[rp].tick;
+            gpioSample[wp].level = level;
+            wp++;
+
+            changedBits |= (newLevel ^ oldLevel);
+
+            oldLevel = newLevel;
+         }
+      }
+
+      numSamples = wp;
+
+      /* Write compacted samples. */
 
       if (changedBits)
       {
@@ -5127,29 +5310,23 @@ static void * pthAlertThread(void *x)
          }
       }
 
-      /* reset timeouts for any changed bits */
+      /* Apply activity filter */
 
-      if (changedBits)
-      {
-         for (b=0; b<=PI_MAX_USER_GPIO; b++)
-         {
-            if (changedBits & (1<<b)) gpioAlert[b].tick = tick;
-         }
-      }
+      alertActivityFilter(numSamples);
 
       /* call alert callbacks for each bit transition */
 
-      if (changedBits & alertBits)
+      if ((changedBits & alertBits) & (~filterBits))
       {
-         oldLevel = reportedLevel & alertBits;
+         oldLevel = (reportedLevel & alertBits) & (~filterBits);
 
          for (d=0; d<numSamples; d++)
          {
-            newLevel = gpioSample[d].level & alertBits;
+            newLevel = (gpioSample[d].level & alertBits) & (~filterBits);
 
             if (newLevel != oldLevel)
             {
-               changes = newLevel ^ oldLevel;
+               changes = (newLevel ^ oldLevel) & (~filterBits);
 
                for (b=0; b<=PI_MAX_USER_GPIO; b++)
                {
@@ -5178,33 +5355,33 @@ static void * pthAlertThread(void *x)
          }
       }
 
-      /* check for timeout watchdogs */
+      /* check for watchdog timeouts */
 
       timeoutBits = 0;
 
       for (b=0; b<=PI_MAX_USER_GPIO; b++)
       {
-         if (gpioAlert[b].timeout)
+         if (gpioAlert[b].wdSteadyUs)
          {
-            diff = tick - gpioAlert[b].tick;
+            diff = stick - gpioAlert[b].wdTick;
 
-            if (diff > (gpioAlert[b].timeout*1000))
+            if (diff >= gpioAlert[b].wdSteadyUs)
             {
                timeoutBits |= (1<<b);
 
-               gpioAlert[b].tick += (gpioAlert[b].timeout*1000);
+               gpioAlert[b].wdTick += gpioAlert[b].wdSteadyUs;
 
                if (gpioAlert[b].func)
                {
                   if (gpioAlert[b].ex)
                   {
                      (gpioAlert[b].func)
-                        (b, PI_TIMEOUT, tick, gpioAlert[b].userdata);
+                        (b, PI_TIMEOUT, stick, gpioAlert[b].userdata);
                   }
                   else
                   {
                      (gpioAlert[b].func)
-                        (b, PI_TIMEOUT, tick);
+                        (b, PI_TIMEOUT, stick);
                   }
                }
             }
@@ -5228,7 +5405,7 @@ static void * pthAlertThread(void *x)
          }
          else if (gpioNotify[n].state == PI_NOTIFY_RUNNING)
          {
-            bits = gpioNotify[n].bits;
+            bits = gpioNotify[n].bits & (~filterBits);
 
             emit = 0;
 
@@ -5254,7 +5431,8 @@ static void * pthAlertThread(void *x)
                      gpioReport[emit].seqno = seqno;
                      gpioReport[emit].flags = 0;
                      gpioReport[emit].tick  = gpioSample[d].tick;
-                     gpioReport[emit].level = gpioSample[d].level;
+                     gpioReport[emit].level =
+                        gpioSample[d].level & (~filterBits);
 
                      oldLevel = newLevel;
 
@@ -5271,6 +5449,8 @@ static void * pthAlertThread(void *x)
                timeoutBits is the set of timed out bits
             */
 
+            bits = gpioNotify[n].bits;
+
             if (timeoutBits & bits)
             {
                /* at least one watchdog has fired for this
@@ -5289,7 +5469,7 @@ static void * pthAlertThread(void *x)
                      gpioReport[emit].seqno = seqno;
                      gpioReport[emit].flags = PI_NTFY_FLAGS_WDOG |
                                               PI_NTFY_FLAGS_BIT(b);
-                     gpioReport[emit].tick  = tick;
+                     gpioReport[emit].tick  = stick;
                      gpioReport[emit].level = newLevel;
 
                      emit++;
@@ -5300,7 +5480,7 @@ static void * pthAlertThread(void *x)
 
             if (!emit)
             {
-               if ((tick - gpioNotify[n].lastReportTick) > 60000000)
+               if ((stick - gpioNotify[n].lastReportTick) > 60000000)
                {
                   if (numSamples)
                      newLevel = gpioSample[numSamples-1].level;
@@ -5309,7 +5489,7 @@ static void * pthAlertThread(void *x)
 
                   gpioReport[emit].seqno = seqno;
                   gpioReport[emit].flags = PI_NTFY_FLAGS_ALIVE;
-                  gpioReport[emit].tick  = tick;
+                  gpioReport[emit].tick  = stick;
                   gpioReport[emit].level = newLevel;
 
                   emit++;
@@ -5319,7 +5499,7 @@ static void * pthAlertThread(void *x)
 
             if (emit)
             {
-               gpioNotify[n].lastReportTick = tick;
+               gpioNotify[n].lastReportTick = stick;
                max_emits = gpioNotify[n].max_emits;
 
                if (emit > gpioStats.maxEmit) gpioStats.maxEmit = emit;
@@ -9785,14 +9965,14 @@ static int intGpioSetISRFunc(
          gpioISR[gpio].pth = NULL;
       }
 
-      if (gpioISR[gpio].inited) /* unexport any gpio */
+      if (gpioISR[gpio].inited) /* unexport the gpio */
       {
          fd = open("/sys/class/gpio/unexport", O_WRONLY);
          if (fd < 0) return PI_BAD_ISR_INIT;
          sprintf(buf, "%d\n", gpio);
          err = write(fd, buf, strlen(buf));
          close(fd);
-         if (err != sizeof(buf)) return PI_BAD_ISR_INIT;
+         if (err != strlen(buf)) return PI_BAD_ISR_INIT;
          gpioISR[gpio].inited = 0;
       }
    }
@@ -10093,8 +10273,72 @@ int gpioSetWatchdog(unsigned gpio, unsigned timeout)
       SOFT_ERROR(PI_BAD_WDOG_TIMEOUT,
          "gpio %d, bad timeout (%d)", gpio, timeout);
 
-   gpioAlert[gpio].timeout = timeout;
-   gpioAlert[gpio].tick    = systReg[SYST_CLO];
+   gpioAlert[gpio].wdTick   = systReg[SYST_CLO];
+   gpioAlert[gpio].wdSteadyUs = timeout*1000;
+
+   return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioNoiseFilter(unsigned gpio, unsigned steady, unsigned active)
+{
+   DBG(DBG_USER, "gpio=%d steady=%d active=%d", gpio, steady, active);
+
+   CHECK_INITED;
+
+   if (gpio > PI_MAX_USER_GPIO)
+      SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
+
+   if (steady > PI_MAX_STEADY)
+      SOFT_ERROR(PI_BAD_FILTER, "bad steady (%d)", steady);
+
+   if (active > PI_MAX_ACTIVE)
+      SOFT_ERROR(PI_BAD_FILTER, "bad active (%d)", active);
+
+   gpioAlert[gpio].fnTick  = systReg[SYST_CLO];
+   gpioAlert[gpio].fnTick2  = gpioAlert[gpio].fnTick;
+   gpioAlert[gpio].fnSteadyUs = steady;
+   gpioAlert[gpio].fnActiveUs = active;
+
+   if (steady) filterBits |= (1<<gpio);
+   else        filterBits &= (~(1<<gpio));
+
+   return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+int gpioGlitchFilter(unsigned gpio, unsigned steady)
+{
+   DBG(DBG_USER, "gpio=%d steady=%d", gpio, steady);
+
+   CHECK_INITED;
+
+   if (gpio > PI_MAX_USER_GPIO)
+      SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
+
+   if (steady > PI_MAX_STEADY)
+      SOFT_ERROR(PI_BAD_FILTER, "bad steady (%d)", steady);
+
+   if (steady)
+   {
+      gpioAlert[gpio].fgTick  = systReg[SYST_CLO];
+
+      if (gpioRead_Bits_0_31() & (1<<gpio))
+      {
+         gpioAlert[gpio].fgLBitV = (1<<gpio);
+         gpioAlert[gpio].fgRBitV = 0 ;
+      }
+      else
+      {
+         gpioAlert[gpio].fgLBitV = 0 ;
+         gpioAlert[gpio].fgRBitV = (1<<gpio);
+      }
+   }
+
+   gpioAlert[gpio].fgDebounceUs = steady;
 
    return 0;
 }
index 2d7700306b89ba8020ad3c63cdcb9adfe8828289..bae30c7c2cc5ac1a1c799accd8c562ab29639f38 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 38
+#define PIGPIO_VERSION 39
 
 /*TEXT
 
@@ -184,6 +184,9 @@ gpioSerialReadClose        Closes a gpio for bit bang serial reads
 gpioHardwareClock          Start hardware clock on supported gpios
 gpioHardwarePWM            Start hardware PWM on supported gpios
 
+gpioGlitchFilter           Set a glitch filter on a gpio
+gpioNoiseFilter            Set a noise filter on a gpio
+
 SCRIPTS
 
 gpioStoreScript            Store a script
@@ -736,6 +739,11 @@ typedef void *(gpioThreadFunc_t) (void *);
 #define PI_MEM_ALLOC_PAGEMAP 1
 #define PI_MEM_ALLOC_MAILBOX 2
 
+/* filters */
+
+#define PI_MAX_STEADY  300000
+#define PI_MAX_ACTIVE 1000000
+
 /* gpioCfgInternals */
 
 #define PI_CFG_DBG_LEVEL         0 /* bits 0-3 */
@@ -2882,6 +2890,52 @@ gpioSetWatchdog(4, 5);
 D*/
 
 
+/*F*/
+int gpioNoiseFilter(unsigned user_gpio, unsigned steady, unsigned active);
+/*D
+Sets a noise filter on a gpio.
+
+Level changes on the gpio are ignored until a level which has
+been stable for [*steady*] microseconds is detected.  Level changes
+on the gpio are then reported for [*active*] microseconds after
+which the process repeats.
+
+. .
+user_gpio: 0-31
+   steady: 0-300000
+   active: 0-1000000
+. .
+
+Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER.
+
+Note, level changes before and after the active period may
+be reported.  Your software must be designed to cope with
+such reports.
+D*/
+
+
+/*F*/
+int gpioGlitchFilter(unsigned user_gpio, unsigned steady);
+/*D
+Sets a glitch filter on a gpio.
+
+Level changes on the gpio are not reported unless the level
+has been stable for at least [*steady*] microseconds.  The
+level is then reported.  Level changes of less than [*steady*]
+microseconds are ignored.
+
+. .
+user_gpio: 0-31
+   steady: 0-300000
+. .
+
+Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER.
+
+Note, each (stable) edge will be timestamped [*steady*] microseconds
+after it was first detected.
+D*/
+
+
 /*F*/
 int gpioSetGetSamplesFunc(gpioGetSamplesFunc_t f, uint32_t bits);
 /*D
@@ -3945,6 +3999,12 @@ D*/
 
 /*PARAMS
 
+active :: 0-1000000
+
+The number of microseconds level changes are reported for once
+a noise filter has been triggered (by [*steady*] microseconds of
+a stable level).
+
 *arg::
 
 A pointer to a void object passed to a thread started by gpioStartThread.
@@ -4580,6 +4640,12 @@ The SPI slave select gpio in a raw SPI transaction.
 spiTxBits::
 The number of bits to transfer dring a raw SPI transaction
 
+steady :: 0-300000
+
+The number of microseconds level changes must be stable for
+before reporting the level changed ([*gpioGlitchFilter*]) or triggering
+the active part of a noise filter ([*gpioNoiseFilter*]).
+
 stop_bits::2-8
 The number of (half) stop bits to be used when adding serial data
 to a waveform.
@@ -4786,6 +4852,9 @@ PARAMS*/
 #define PI_CMD_CGI   95
 #define PI_CMD_CSI   96
 
+#define PI_CMD_FG    97
+#define PI_CMD_FN    98
+
 #define PI_CMD_NOIB  99
 
 /*DEF_E*/
@@ -4975,6 +5044,7 @@ after this command is issued.
 #define PI_BAD_EDGE        -122 // bad ISR edge value, not 0-2
 #define PI_BAD_ISR_INIT    -123 // bad ISR initialisation
 #define PI_BAD_FOREVER     -124 // loop forever must be last chain command
+#define PI_BAD_FILTER      -125 // bad filter parameter
 
 #define PI_PIGIF_ERR_0    -2000
 #define PI_PIGIF_ERR_99   -2099
index 2771dfbe1ddc5f2f30f648be31c30081dd79b13b..965d9b72bb17c50a9b2e3837af21f9346d60436c 100644 (file)
--- a/pigpio.py
+++ b/pigpio.py
@@ -123,6 +123,7 @@ Intermediate
 gpio_trigger              Send a trigger pulse to a gpio
 
 set_watchdog              Set a watchdog on a gpio
+set_filter                Set an activity filter on a gpio
 
 set_PWM_range             Configure PWM range of a gpio
 get_PWM_range             Get configured PWM range of a gpio
@@ -156,6 +157,9 @@ bb_serial_invert          Invert serial logic (1 invert, 0 normal)
 hardware_clock            Start hardware clock on supported gpios
 hardware_PWM              Start hardware PWM on supported gpios
 
+set_glitch_filter         Set a glitch filter on a gpio
+set_noise_filter          Set a noise filter on a gpio
+
 Scripts
 
 store_script              Store a script
@@ -256,6 +260,7 @@ get_pigpio_version        Get the pigpio version
 pigpio.error_text         Gets error text from error number
 pigpio.tickDiff           Returns difference between two ticks
 """
+
 import sys
 import socket
 import struct
@@ -264,7 +269,7 @@ import threading
 import os
 import atexit
 
-VERSION = "1.22"
+VERSION = "1.23"
 
 exceptions = True
 
@@ -435,6 +440,12 @@ _PI_CMD_WVCHA=93
 
 _PI_CMD_SLRI =94
 
+_PI_CMD_CGI  =95
+_PI_CMD_CSI  =96
+
+_PI_CMD_FG   =97
+_PI_CMD_FN   =98
+
 # pigpio error numbers
 
 _PI_INIT_FAILED     =-1
@@ -559,6 +570,11 @@ PI_CHAIN_NESTING    =-118
 PI_CHAIN_TOO_BIG    =-119
 PI_DEPRECATED       =-120
 PI_BAD_SER_INVERT   =-121
+_PI_BAD_EDGE        =-122
+_PI_BAD_ISR_INIT    =-123
+PI_BAD_FOREVER      =-124
+PI_BAD_FILTER       =-125
+
 
 # pigpio error text
 
@@ -682,6 +698,10 @@ _errors=[
    [PI_CHAIN_TOO_BIG     , "chain is too long"],
    [PI_DEPRECATED        , "deprecated function removed"],
    [PI_BAD_SER_INVERT    , "bit bang serial invert not 0 or 1"],
+   [_PI_BAD_EDGE         , "bad ISR edge value, not 0-2"],
+   [_PI_BAD_ISR_INIT     , "bad ISR initialisation"],
+   [PI_BAD_FOREVER       , "loop forever must be last chain command"],
+   [PI_BAD_FILTER        , "bad filter parameter"],
 
 ]
 
@@ -867,6 +887,7 @@ class _callback_thread(threading.Thread):
       self.monitor = 0
       self.callbacks = []
       self.sl.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+      self.sl.s.settimeout(None)
       self.sl.s.connect((host, port))
       self.handle = _pigpio_command(self.sl, _PI_CMD_NOIB, 0, 0)
       self.go = True
@@ -3215,6 +3236,63 @@ class pi():
       return _u2i(_pigpio_command_ext(
          self.sl, _PI_CMD_TRIG, user_gpio, pulse_len, 4, extents))
 
+   def set_glitch_filter(self, user_gpio, steady):
+      """
+      Sets a glitch filter on a gpio.
+
+      Level changes on the gpio are not reported unless the level
+      has been stable for at least [*steady*] microseconds.  The
+      level is then reported.  Level changes of less than [*steady*]
+      microseconds are ignored.
+
+      user_gpio:= 0-31
+         steady:= 0-300000
+
+      Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER.
+
+      Note, each (stable) edge will be timestamped [*steady*]
+      microseconds after it was first detected.
+
+      ...
+      pi.set_glitch_filter(23, 100)
+      ...
+      """
+      return _u2i(_pigpio_command(self.sl, _PI_CMD_FG, user_gpio, steady))
+
+   def set_noise_filter(self, user_gpio, steady, active):
+      """
+      Sets a noise filter on a gpio.
+
+      Level changes on the gpio are ignored until a level which has
+      been stable for [*steady*] microseconds is detected.  Level
+      changes on the gpio are then reported for [*active*]
+      microseconds after which the process repeats.
+
+      user_gpio:= 0-31
+         steady:= 0-300000
+         active:= 0-1000000
+
+      Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER.
+
+      Note, level changes before and after the active period may
+      be reported.  Your software must be designed to cope with
+      such reports.
+
+      ...
+      pi.set_noise_filter(23, 1000, 5000)
+      ...
+      """
+      # pigpio message format
+
+      # I p1 user_gpio
+      # I p2 steady
+      # I p3 4
+      ## extension ##
+      # I active
+      extents = [struct.pack("I", active)]
+      return _u2i(_pigpio_command_ext(
+         self.sl, _PI_CMD_FN, user_gpio, steady, 4, extents))
+
    def store_script(self, script):
       """
       Store a script for later execution.
@@ -3600,6 +3678,7 @@ class pi():
       self._port = int(port)
 
       self.sl.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+      self.sl.s.settimeout(None)
 
       # Disable the Nagle algorithm.
       self.sl.s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
@@ -3653,6 +3732,12 @@ class pi():
 
 def xref():
    """
+   active: 0-1000000
+   The number of microseconds level changes are reported for once
+   a noise filter has been triggered (by [*steady*] microseconds of
+   a stable level).
+
+
    arg1:
    An unsigned argument passed to a user customised function.  Its
    meaning is defined by the customiser.
@@ -3982,6 +4067,13 @@ def xref():
    spi_flags: 32 bit
    See [*spi_open*].
 
+   steady: 0-300000
+
+   The number of microseconds level changes must be stable for
+   before reporting the level changed ([*set_glitch_filter*])
+   or triggering the active part of a noise filter
+   ([*set_noise_filter*]).
+
    t1:
    A tick (earlier).
 
index 3e29b501139536a8a1d4d401d1b77887f7ac815b..fac7b707d8f7a8ebe553cd3755ae446008184628 100644 (file)
@@ -1014,6 +1014,79 @@ to the fifo with the flags set to indicate a watchdog timeout.
 The \fBcallback\fP and \fBcallback_ex\fP functions interpret the flags
 and will call registered callbacks for the gpio with level TIMEOUT.
 
+.IP "\fBint set_glitch_filter(unsigned user_gpio, unsigned steady)\fP"
+.IP "" 4
+Sets a glitch filter on a gpio.
+
+.br
+
+.br
+Level changes on the gpio are not reported unless the level
+has been stable for at least \fBsteady\fP microseconds.  The
+level is then reported.  Level changes of less than \fBsteady\fP
+microseconds are ignored.
+
+.br
+
+.br
+
+.EX
+user_gpio: 0-31
+.br
+   steady: 0-300000
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER.
+
+.br
+
+.br
+Note, each (stable) edge will be timestamped \fBsteady\fP microseconds
+after it was first detected.
+
+.IP "\fBint set_noise_filter(unsigned user_gpio, unsigned steady, unsigned active)\fP"
+.IP "" 4
+Sets a noise filter on a gpio.
+
+.br
+
+.br
+Level changes on the gpio are ignored until a level which has
+been stable for \fBsteady\fP microseconds is detected.  Level changes
+on the gpio are then reported for \fBactive\fP microseconds after
+which the process repeats.
+
+.br
+
+.br
+
+.EX
+user_gpio: 0-31
+.br
+   steady: 0-300000
+.br
+   active: 0-1000000
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER.
+
+.br
+
+.br
+Note, level changes before and after the active period may
+be reported.  Your software must be designed to cope with
+such reports.
+
 .IP "\fBuint32_t read_bank_1(void)\fP"
 .IP "" 4
 Read the levels of the bank 1 gpios (gpios 0-31).
@@ -3697,8 +3770,7 @@ the gpio has the identified edge.
 
 .IP "\fBint callback_cancel(unsigned callback_id)\fP"
 .IP "" 4
-This function fim
-cancels a callback identified by its id.
+This function cancels a callback identified by its id.
 
 .br
 
@@ -3749,6 +3821,19 @@ The function returns when the edge occurs or after the timeout.
 
 .br
 
+.IP "\fBactive\fP: 0-1000000" 0
+
+.br
+
+.br
+The number of microseconds level changes are reported for once
+a noise filter has been triggered (by \fBsteady\fP microseconds of
+a stable level).
+
+.br
+
+.br
+
 .IP "\fB*addrStr\fP" 0
 A string specifying the host or IP address of the Pi running
 the pigpio daemon.  It may be NULL in which case localhost
@@ -4508,6 +4593,19 @@ See \fBspi_open\fP.
 
 .br
 
+.IP "\fBsteady\fP: 0-300000" 0
+
+.br
+
+.br
+The number of microseconds level changes must be stable for
+before reporting the level changed (\fBset_glitch_filter\fP) or triggering
+the active part of a noise filter (\fBset_noise_filter\fP).
+
+.br
+
+.br
+
 .IP "\fBstop_bits\fP: 2-8" 0
 The number of (half) stop bits to be used when adding serial data
 to a waveform.
index e36a0fd6f9c35e0cbd1ff85d7e505c50c8dbfbf2..4078e126fd6c52f5adfac22c00b8469631b8c330 100644 (file)
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 For more information, please refer to <http://unlicense.org/>
 */
 
-/* PIGPIOD_IF_VERSION 19 */
+/* PIGPIOD_IF_VERSION 21 */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -740,10 +740,10 @@ int wave_tx_repeat(void) /* DEPRECATED */
    {return pigpio_command(gPigCommand, PI_CMD_WVGOR, 0, 0, 1);}
 
 int wave_send_once(unsigned wave_id)
-   {return pigpio_command(gPigCommand, PI_CMD_WVTX, 0, 0, 1);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVTX, wave_id, 0, 1);}
 
 int wave_send_repeat(unsigned wave_id)
-   {return pigpio_command(gPigCommand, PI_CMD_WVTXR, 0, 0, 1);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVTXR, wave_id, 0, 1);}
 
 int wave_chain(char *buf, unsigned bufSize)
 {
@@ -816,6 +816,28 @@ int gpio_trigger(unsigned user_gpio, unsigned pulseLen, uint32_t level)
       gPigCommand, PI_CMD_TRIG, user_gpio, pulseLen, 4, 1, ext, 1);
 }
 
+int set_glitch_filter(unsigned user_gpio, unsigned steady)
+   {return pigpio_command(gPigCommand, PI_CMD_FG, user_gpio, steady, 1);}
+
+int set_noise_filter(unsigned user_gpio, unsigned steady, unsigned active)
+{
+   gpioExtent_t ext[1];
+   
+   /*
+   p1=user_gpio
+   p2=steady
+   p3=4
+   ## extension ##
+   unsigned active
+   */
+
+   ext[0].size = sizeof(uint32_t);
+   ext[0].ptr = &active;
+
+   return pigpio_command_ext(
+      gPigCommand, PI_CMD_FN, user_gpio, steady, 4, 1, ext, 1);
+}
+
 int store_script(char *script)
 {
    unsigned len;
index 7d6a630cf5504e554b7f588211425f7dbcc4e930..b819464115c05cb1cc4ec9eae79aa2dbfb58a324 100644 (file)
@@ -30,7 +30,7 @@ For more information, please refer to <http://unlicense.org/>
 
 #include "pigpio.h"
 
-#define PIGPIOD_IF_VERSION 20
+#define PIGPIOD_IF_VERSION 21
 
 /*TEXT
 
@@ -166,6 +166,9 @@ bb_serial_invert           Invert serial logic (1 invert, 0 normal)
 hardware_clock             Start hardware clock on supported gpios
 hardware_PWM               Start hardware PWM on supported gpios
 
+set_glitch_filter         Set a glitch filter on a gpio
+set_noise_filter          Set a noise filter on a gpio
+
 SCRIPTS
 
 store_script               Store a script
@@ -275,6 +278,9 @@ time_time                  Float number of seconds since the epoch
 
 OVERVIEW*/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 typedef void (*CBFunc_t)  (unsigned user_gpio, unsigned level, uint32_t tick);
 
@@ -780,6 +786,50 @@ The [*callback*] and [*callback_ex*] functions interpret the flags
 and will call registered callbacks for the gpio with level TIMEOUT.
 D*/
 
+/*F*/
+int set_glitch_filter(unsigned user_gpio, unsigned steady);
+/*D
+Sets a glitch filter on a gpio.
+
+Level changes on the gpio are not reported unless the level
+has been stable for at least [*steady*] microseconds.  The
+level is then reported.  Level changes of less than [*steady*]
+microseconds are ignored.
+
+. .
+user_gpio: 0-31
+   steady: 0-300000
+. .
+
+Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER.
+
+Note, each (stable) edge will be timestamped [*steady*] microseconds
+after it was first detected.
+D*/
+
+/*F*/
+int set_noise_filter(unsigned user_gpio, unsigned steady, unsigned active);
+/*D
+Sets a noise filter on a gpio.
+
+Level changes on the gpio are ignored until a level which has
+been stable for [*steady*] microseconds is detected.  Level changes
+on the gpio are then reported for [*active*] microseconds after
+which the process repeats.
+
+. .
+user_gpio: 0-31
+   steady: 0-300000
+   active: 0-1000000
+. .
+
+Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_BAD_FILTER.
+
+Note, level changes before and after the active period may
+be reported.  Your software must be designed to cope with
+such reports.
+D*/
+
 /*F*/
 uint32_t read_bank_1(void);
 /*D
@@ -2367,8 +2417,7 @@ D*/
 /*F*/
 int callback_cancel(unsigned callback_id);
 /*D
-This function fim
-cancels a callback identified by its id.
+This function cancels a callback identified by its id.
 
 . .
 callback_id: >=0, as returned by a call to [*callback*] or [*callback_ex*].
@@ -2396,6 +2445,12 @@ D*/
 
 /*PARAMS
 
+active :: 0-1000000
+
+The number of microseconds level changes are reported for once
+a noise filter has been triggered (by [*steady*] microseconds of
+a stable level).
+
 *addrStr::
 A string specifying the host or IP address of the Pi running
 the pigpio daemon.  It may be NULL in which case localhost
@@ -2737,6 +2792,12 @@ A SPI channel, 0-2.
 spi_flags::
 See [*spi_open*].
 
+steady :: 0-300000
+
+The number of microseconds level changes must be stable for
+before reporting the level changed ([*set_glitch_filter*]) or triggering
+the active part of a noise filter ([*set_noise_filter*]).
+
 stop_bits::2-8
 The number of (half) stop bits to be used when adding serial data
 to a waveform.
@@ -2813,5 +2874,9 @@ typedef enum
 
 /*DEF_E*/
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
 
diff --git a/pigs.1 b/pigs.1
index 061255af15ade1c52f3303515917d0b41563a3af..a3706e633ee4017358b02d46a7f77604adfbcb4b 100644 (file)
--- a/pigs.1
+++ b/pigs.1
@@ -514,6 +514,37 @@ configuration settings to \fBv\fP.
 
 .br
 
+.IP "\fBFG u stdy\fP - Set a glitch filter on a gpio"
+.IP "" 4
+
+.br
+Level changes on the gpio are not reported unless the level
+has been stable for at least \fBstdy\fP microseconds.  The
+level is then reported.  Level changes of less than \fBstdy\fP
+microseconds are ignored.
+
+.br
+Note, each (stable) edge will be timestamped \fBstdy\fP microseconds
+after it was first detected.
+
+.br
+
+.IP "\fBFN u stdy actv\fP - Set a noise filter on a gpio"
+.IP "" 4
+
+.br
+Level changes on the gpio are ignored until a level which has
+been stable for \fBstdy\fP microseconds is detected.  Level
+changes on the gpio are then reported for \fBactv\fP microseconds
+after which the process repeats.
+
+.br
+Note, level changes before and after the active period may
+be reported.  Your software must be designed to cope with
+such reports.
+
+.br
+
 .IP "\fBGDC u\fP - Get gpio PWM dutycycle"
 .IP "" 4
 
@@ -3696,6 +3727,15 @@ ERROR: non existent wave id
 
 .br
 
+.IP "\fBactv\fP - 0-1000000" 0
+
+.br
+The number of microseconds level changes are reported for once
+a noise filter has been triggered (by \fBstdy\fP microseconds of
+a stable level).
+
+.br
+
 .IP "\fBb\fP - baud" 0
 The command expects the baud rate in bits per second for
 the transmission of serial data (I2C/SPI/serial link, waves).
@@ -3958,6 +3998,15 @@ See \fBSPIO\fP.
 
 .br
 
+.IP "\fBstdy\fP - 0-300000" 0
+
+.br
+The number of microseconds level changes must be stable for
+before reporting the level changed (\fBFG\fP) or triggering
+the active part of a noise filter (\fBFN\fP).
+
+.br
+
 .IP "\fBt\fP - text (a string of text)" 0
 The command expects a text string.
 
index 958444e560104b97336e477f5889ba582cc1801f..a7df3a0ddf1e852a0bf6da6d067ff83bacb3bc14 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
 from distutils.core import setup
 
 setup(name='pigpio',
-      version='1.22',
+      version='1.23',
       author='joan',
       author_email='joan@abyz.co.uk',
       maintainer='joan',
diff --git a/x_pigs b/x_pigs
index a8b8d2179d9889019bffb1e845a37ad79dd000d2..14b22e83665bda776f60b42dc550353e64361ddd 100755 (executable)
--- a/x_pigs
+++ b/x_pigs
@@ -49,7 +49,7 @@ s=$(pigs bs2 0)
 if [[ $s = "" ]]; then echo "BS2 ok"; else echo "BS2 fail ($s)"; fi
 
 s=$(pigs h)
-if [[ ${#s} = 4412 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
+if [[ ${#s} = 4502 ]]; 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