This commit is contained in:
joan 2015-10-28 11:06:53 +00:00
parent f5912f84b4
commit b140e1aa74
11 changed files with 823 additions and 69 deletions

View File

@ -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"},
};

107
pigpio.3
View File

@ -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

352
pigpio.c
View File

@ -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].tick = stick;
gpioSample[numSamples].level = level;
changedBits |= (newLevel ^ oldLevel);
oldLevel = newLevel;
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;
}

View File

@ -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

View File

@ -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).

View 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.

View 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;

View 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

49
pigs.1
View File

@ -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.

View File

@ -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',

2
x_pigs
View File

@ -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