This commit is contained in:
joan 2014-01-21 19:04:59 +00:00
parent 7f0cf5a014
commit 23e3b179ab
13 changed files with 1676 additions and 443 deletions

View File

@ -5,11 +5,11 @@ SIZE = size
CFLAGS = -O3 -Wall CFLAGS = -O3 -Wall
ALL = libpigpiod_if.a pigs ALL = libpigpiod_if.a pigs pigpio.py setup.py
all: $(ALL) all: $(ALL)
pigs: command.o pigs: command.o pigs.o
$(CC) -o pigs pigs.c command.c $(CC) -o pigs pigs.c command.c
clean: clean:
@ -41,7 +41,7 @@ $(LIB): $(OBJ)
# generated using gcc -MM *.c # generated using gcc -MM *.c
command.o: command.c pigpio.h command.h command.o: command.c pigpio.h command.h
pigpiod.o: pigpiod.c pigpio.h command.h pigpiod.o: pigpiod.c pigpio.h
pigpiod_if.o: pigpiod_if.c pigpio.h pigpiod_if.h pigpiod_if.o: pigpiod_if.c pigpio.h pigpiod_if.h command.h
pigs.o: pigs.c pigpio.h command.h pigs.o: pigs.c pigpio.h command.h

View File

@ -72,7 +72,7 @@ checklib.o: checklib.c pigpio.h
command.o: command.c pigpio.h command.h command.o: command.c pigpio.h command.h
pig2vcd.o: pig2vcd.c pigpio.h pig2vcd.o: pig2vcd.c pigpio.h
pigpio.o: pigpio.c pigpio.h command.h pigpio.o: pigpio.c pigpio.h command.h
pigpiod.o: pigpiod.c pigpio.h command.h pigpiod.o: pigpiod.c pigpio.h
pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h
pigs.o: pigs.c pigpio.h command.h pigs.o: pigs.c pigpio.h command.h

3
README
View File

@ -31,8 +31,7 @@ EXAMPLE CODE
checklib.c, pig2vcd.c, and pigpiod.c checklib.c, pig2vcd.c, and pigpiod.c
show examples of interfacing with the pigpio library. show examples of interfacing with the pigpio library.
pigs.c, pigpio.py, and test_pigpiod_if.c pigs.c and pigpio.py show examples of interfacing with the pigpiod daemon.
show examples of interfacing with the pigpiod daemon.
DAEMON DAEMON

273
command.c
View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 10+ This version is for pigpio version 11+
*/ */
#include <stdio.h> #include <stdio.h>
@ -38,79 +38,144 @@ This version is for pigpio version 10+
#include "pigpio.h" #include "pigpio.h"
#include "command.h" #include "command.h"
/* retv
pigs pipe
0 "" <0 ERR %d
1 "" <0 ERR %d
2 %d <0 ERR %d
3 %08X %08X
4 %u %u
5 HELP HELP
*/
/* vfyt
1 cmd
2 cmd %d
3 cmd %d %d
4 cmd %d %x
6 HELP
7 cmd %x
8 MODES %d %c
9 PUD %d %c
10 PROG %s
*/
cmdInfo_t cmdInfo[]= cmdInfo_t cmdInfo[]=
{ {
{PI_CMD_BR1, "BR1", 1, 3}, /* num str vfyt retv ext */
{PI_CMD_BR2, "BR2", 1, 3},
{PI_CMD_BC1, "BC1", 7, 1}, {PI_CMD_BC1, "BC1", 7, 1, 0},
{PI_CMD_BC2, "BC2", 7, 1}, {PI_CMD_BC2, "BC2", 7, 1, 0},
{PI_CMD_BS1, "BS1", 7, 1}, {PI_CMD_BR1, "BR1", 1, 3, 0},
{PI_CMD_BS2, "BS2", 7, 1}, {PI_CMD_BR2, "BR2", 1, 3, 0},
{PI_CMD_HWVER, "HWVER", 1, 4}, {PI_CMD_BS1, "BS1", 7, 1, 0},
{PI_CMD_MODES, "MODES", 8, 0}, {PI_CMD_BS2, "BS2", 7, 1, 0},
{PI_CMD_MODES, "M", 8, 0}, {PI_CMD_HELP, "H", 6, 5, 0},
{PI_CMD_MODEG, "MODEG", 2, 2}, {PI_CMD_HELP, "HELP", 6, 5, 0},
{PI_CMD_MODEG, "MG" , 2, 2}, {PI_CMD_HWVER, "HWVER", 1, 4, 0},
{PI_CMD_NO, "NO", 1, 2}, {PI_CMD_MODEG, "MG" , 2, 2, 0},
{PI_CMD_NB, "NB", 4, 0}, {PI_CMD_MODEG, "MODEG", 2, 2, 0},
{PI_CMD_NP, "NP", 2, 0}, {PI_CMD_MODES, "M", 8, 0, 0},
{PI_CMD_NC, "NC", 2, 0}, {PI_CMD_MODES, "MODES", 8, 0, 0},
{PI_CMD_PWM, "PWM", 3, 0}, {PI_CMD_NB, "NB", 4, 0, 0},
{PI_CMD_PWM, "P", 3, 0}, {PI_CMD_NC, "NC", 2, 0, 0},
{PI_CMD_PFS, "PFS", 3, 2}, {PI_CMD_NO, "NO", 1, 2, 0},
{PI_CMD_PFG, "PFG", 2, 2}, {PI_CMD_NP, "NP", 2, 0, 0},
{PI_CMD_PRS, "PRS", 3, 2}, {PI_CMD_PFG, "PFG", 2, 2, 0},
{PI_CMD_PRG, "PRG", 2, 2}, {PI_CMD_PFS, "PFS", 3, 2, 0},
{PI_CMD_PRRG, "PRRG", 2, 2}, {PI_CMD_PIGPV, "PIGPV", 1, 4, 0},
{PI_CMD_PUD, "PUD", 9, 0}, {PI_CMD_PRG, "PRG", 2, 2, 0},
{PI_CMD_READ, "READ", 2, 2}, {PI_CMD_PROC, "PROC", 10, 2, 1},
{PI_CMD_READ, "R", 2, 2}, {PI_CMD_PROCD, "PROCD", 2, 2, 0},
{PI_CMD_SERVO, "SERVO", 3, 0}, {PI_CMD_PROCR, "PROCR", 2, 2, 0},
{PI_CMD_SERVO, "S", 3, 0}, {PI_CMD_PROCS, "PROCS", 2, 2, 0},
{PI_CMD_WRITE, "WRITE", 3, 0}, {PI_CMD_PRRG, "PRRG", 2, 2, 0},
{PI_CMD_WRITE, "W", 3, 0}, {PI_CMD_PRS, "PRS", 3, 2, 0},
{PI_CMD_WDOG, "WDOG", 3, 0}, {PI_CMD_PUD, "PUD", 9, 0, 0},
{PI_CMD_TICK, "TICK", 1, 4}, {PI_CMD_PWM, "P", 3, 0, 0},
{PI_CMD_TICK, "T", 1, 4}, {PI_CMD_PWM, "PWM", 3, 0, 0},
{PI_CMD_HELP, "HELP", 6, 5}, {PI_CMD_READ, "R", 2, 2, 0},
{PI_CMD_HELP, "H", 6, 5}, {PI_CMD_READ, "READ", 2, 2, 0},
{PI_CMD_PIGPV, "PIGPV", 1, 4}, {PI_CMD_SERVO, "S", 3, 0, 0},
{PI_CMD_SERVO, "SERVO", 3, 0, 0},
{PI_CMD_WDOG, "WDOG", 3, 0, 0},
{PI_CMD_WRITE, "W", 3, 0, 0},
{PI_CMD_WRITE, "WRITE", 3, 0, 0},
{PI_CMD_TICK, "T", 1, 4, 0},
{PI_CMD_TICK, "TICK", 1, 4, 0},
{PI_CMD_TRIG, "TRIG", 5, 0, 1},
{PI_CMD_WVAS, "WVAS", 11, 2, 3},
{PI_CMD_WVBSY, "WVBSY", 1, 2, 0},
{PI_CMD_WVCLR, "WVCLR", 1, 2, 0},
{PI_CMD_WVGO, "WVGO" , 1, 2, 0},
{PI_CMD_WVGOR, "WVGOR", 1, 2, 0},
{PI_CMD_WVHLT, "WVHLT", 1, 2, 0},
{PI_CMD_WVSC, "WVSC", 2, 2, 0},
{PI_CMD_WVSM, "WVSM", 2, 2, 0},
{PI_CMD_WVSP, "WVSP", 2, 2, 0},
}; };
char * cmdUsage = "\ char * cmdUsage = "\
BR1 read gpios bank 1\n\
BR2 read gpios bank 2\n\
BC1 x clear gpios in bank 1\n\ BC1 x clear gpios in bank 1\n\
BC2 x clear gpios in bank 2\n\ BC2 x clear gpios in bank 2\n\
BR1 read gpios bank 1\n\
BR2 read gpios bank 2\n\
BS1 x set gpios in bank 1\n\ BS1 x set gpios in bank 1\n\
BS2 x set gpios in bank 2\n\ BS2 x set gpios in bank 2\n\
H displays command help\n\
HELP displays command help\n\
HWVER return hardware version\n\ HWVER return hardware version\n\
MODES/M g m set gpio mode\n\ M g m set gpio mode\n\
MODEG/MG g get gpio mode\n\ MG g get gpio mode\n\
NO request notification handle\n\ MODEG g get gpio mode\n\
MODES g m set gpio mode\n\
NB h x start notification\n\ NB h x start notification\n\
NP h pause notification\n\
NC h close notification\n\ NC h close notification\n\
PWM/P u d set PWM value for gpio\n\ NO request notification handle\n\
PFS u d set PWM frequency for gpio\n\ NP h pause notification\n\
P u d set PWM value for gpio\n\
PFG u get PWM frequency for gpio\n\ PFG u get PWM frequency for gpio\n\
PFS u d set PWM frequency for gpio\n\
PIGPV return pigpio version\n\ PIGPV return pigpio version\n\
PRS u d set PWM range for gpio\n\
PRG u get PWM range for gpio\n\ PRG u get PWM range for gpio\n\
PROC t validate and store script\n\
PROCD s delete script\n\
PROCR s run script\n\
PROCS s stop script\n\
PRRG u get PWM real range for gpio\n\ PRRG u get PWM real range for gpio\n\
PRS u d set PWM range for gpio\n\
PUD g p set gpio pull up/down\n\ PUD g p set gpio pull up/down\n\
READ/R g read gpio\n\ PWM u d set PWM value for gpio\n\
SERVO/S u d set servo value for gpio\n\ R g read gpio\n\
WRITE/W g d write value to gpio\n\ READ g read gpio\n\
S u d set servo value for gpio\n\
SERVO u d set servo value for gpio\n\
T return current tick\n\
TICK return current tick\n\
TRIG u pl l trigger level l for pl micros on gpio\n\
W g l write level to gpio\n\
WDOG u d set watchdog on gpio\n\ WDOG u d set watchdog on gpio\n\
TICK/T return current tick\n\ WRITE g l write level to gpio\n\
HELP/H displays command help\n\ WVAS u b t wave add serial data\n\
WVBSY check if wave busy\n\
WVCLR wave clear\n\
WVGO wave transmit\n\
WVGOR wave transmit repeat\n\
WVHLT wave stop\n\
WVSC ws wave get cbs stats\n\
WVSM ws wave get micros stats\n\
WVSP ws wave get pulses stats\n\
\n\ \n\
b = baud rate\n\
d = decimal value\n\ d = decimal value\n\
g = gpio (0-53)\n\ g = gpio (0-53)\n\
h = handle (0-31)\n\ h = handle (0-31)\n\
l = level (0-1)\n\
m = mode (RW540123)\n\ m = mode (RW540123)\n\
p = pud (ODU)\n\ p = pud (ODU)\n\
pl = pulse length (0-100)\n\
s = script id\n\
t = text\n\
u = user gpio (0-31)\n\ u = user gpio (0-31)\n\
x = hex value\n\ x = hex value\n\
"; ";
@ -130,7 +195,7 @@ static errInfo_t errInfo[]=
{PI_BAD_LEVEL , "level not 0-1"}, {PI_BAD_LEVEL , "level not 0-1"},
{PI_BAD_PUD , "pud not 0-2"}, {PI_BAD_PUD , "pud not 0-2"},
{PI_BAD_PULSEWIDTH , "pulsewidth not 0 or 500-2500"}, {PI_BAD_PULSEWIDTH , "pulsewidth not 0 or 500-2500"},
{PI_BAD_DUTYCYCLE , "dutycycle not 0-255"}, {PI_BAD_DUTYCYCLE , "dutycycle outside set range"},
{PI_BAD_TIMER , "timer not 0-9"}, {PI_BAD_TIMER , "timer not 0-9"},
{PI_BAD_MS , "ms not 10-60000"}, {PI_BAD_MS , "ms not 10-60000"},
{PI_BAD_TIMETYPE , "timetype not 0-1"}, {PI_BAD_TIMETYPE , "timetype not 0-1"},
@ -165,6 +230,13 @@ static errInfo_t errInfo[]=
{PI_BAD_SERIAL_BUF , "bad (null) serial buf parameter"}, {PI_BAD_SERIAL_BUF , "bad (null) serial buf parameter"},
{PI_NOT_PERMITTED , "no permission to update gpio"}, {PI_NOT_PERMITTED , "no permission to update gpio"},
{PI_SOME_PERMITTED , "no permission to update one or more gpios"}, {PI_SOME_PERMITTED , "no permission to update one or more gpios"},
{PI_BAD_WVSC_COMMND , "bad WVSC subcommand"},
{PI_BAD_WVSM_COMMND , "bad WVSM subcommand"},
{PI_BAD_WVSP_COMMND , "bad WVSP subcommand"},
{PI_BAD_PULSELEN , "trigger pulse > 100 microseconds"},
{PI_BAD_SCRIPT , "invalid script"},
{PI_BAD_SCRIPT_ID , "unknown script id"},
{PI_BAD_SER_OFFSET , "add serial data offset > 30 minute"},
}; };
static char * fmtMdeStr="RW540123"; static char * fmtMdeStr="RW540123";
@ -181,11 +253,11 @@ static int cmdMatch(char * str)
return -1; return -1;
} }
int cmdParse(char * buf, cmdCmd_t * cmd) int cmdParse(char *buf, cmdCmd_t *cmd, int argc, char *argv[], gpioExtent_t *ext)
{ {
char str[8]; char str[8];
int f, valid, idx, val; int f, valid, idx, val;
char * ptr; char *ptr;
char c, t; char c, t;
sscanf(buf, " %7s", str); sscanf(buf, " %7s", str);
@ -204,36 +276,57 @@ int cmdParse(char * buf, cmdCmd_t * cmd)
switch (cmdInfo[idx].vt) switch (cmdInfo[idx].vt)
{ {
case 1: /* BR1 BR2 HWVER PIGPV NO TICK */ case 1: /* BR1 BR2 HWVER NO PIGPV TICK WVBSY WVCLR WVGO WVGOR
WVHLT
*/
f = sscanf(buf, " %7s %c", str, &t); f = sscanf(buf, " %7s %c", str, &t);
if (f == 1) valid = 1; if (f == 1) valid = 1;
break; break;
case 2: /* MODEG READ NC NP PFG PRG PRRG */ case 2: /* MODEG NC NP PFG PRG PROCD PROCR PROCS PRRG READ
WVSC WVSM WVSP
*/
f = sscanf(buf, " %7s %d %c", str, &cmd->p1, &t); f = sscanf(buf, " %7s %d %c", str, &cmd->p1, &t);
if (f == 2) valid = 1; if (f == 2) valid = 1;
break; break;
case 3: /* WRITE PWM PRS PFS SERVO WDOG */ case 3: /* PFS PRS PWM SERVO WDOG WRITE
*/
f = sscanf(buf, " %7s %d %d %c", str, &cmd->p1, &cmd->p2, &t); f = sscanf(buf, " %7s %d %d %c", str, &cmd->p1, &cmd->p2, &t);
if (f == 3) valid = 1; if (f == 3) valid = 1;
break; break;
case 4: /* NB */ case 4: /* NB
*/
f = sscanf(buf, " %7s %d %x %c", str, &cmd->p1, &cmd->p2, &t); f = sscanf(buf, " %7s %d %x %c", str, &cmd->p1, &cmd->p2, &t);
if (f == 3) valid = 1; if (f == 3) valid = 1;
break; break;
case 6: /* HELP */ case 5: /* TRIG
*/
f = sscanf(buf, " %7s %d %d %d %c",
str, &cmd->p1, &cmd->p2, &ext[0].data, &t);
if (f == 4)
{
ext[0].n = sizeof(unsigned);
ext[0].ptr = &ext[0].data;
valid = 1;
}
break;
case 6: /* HELP
*/
valid = 1; valid = 1;
break; break;
case 7: /* BC1 BC2 BS1 BS2 */ case 7: /* BC1 BC2 BS1 BS2
*/
f = sscanf(buf, " %7s %x %c", str, &cmd->p1, &t); f = sscanf(buf, " %7s %x %c", str, &cmd->p1, &t);
if (f == 2) valid = 1; if (f == 2) valid = 1;
break; break;
case 8: /* MODES */ case 8: /* MODES
*/
f = sscanf(buf, " %7s %d %c %c", str, &cmd->p1, &c, &t); f = sscanf(buf, " %7s %d %c %c", str, &cmd->p1, &c, &t);
if (f == 3) if (f == 3)
{ {
@ -248,7 +341,8 @@ int cmdParse(char * buf, cmdCmd_t * cmd)
} }
break; break;
case 9: /* PUD */ case 9: /* PUD
*/
f = sscanf(buf, " %7s %d %c %c", str, &cmd->p1, &c, &t); f = sscanf(buf, " %7s %d %c %c", str, &cmd->p1, &c, &t);
if (f == 3) if (f == 3)
{ {
@ -262,28 +356,43 @@ int cmdParse(char * buf, cmdCmd_t * cmd)
} }
} }
break; break;
case 10: /* PROC
*/
if (argc == 3)
{
cmd->p1 = strlen(argv[2]);
ext[0].n = cmd->p1;
ext[0].ptr = argv[2];
valid = 1;
}
break;
case 11: /* WVAS
*/
if (argc == 6)
{
f = sscanf(buf, " %7s %d %d %d ",
str, &cmd->p1, &ext[0].data, &ext[1].data);
if (f == 4)
{
ext[0].n = sizeof(unsigned);
ext[0].ptr = &ext[0].data;
ext[1].n = sizeof(unsigned);
ext[1].ptr = &ext[1].data;
cmd->p2 = strlen(argv[5]);
ext[2].n = cmd->p2;
ext[2].ptr = argv[5];
valid = 1;
}
}
break;
} }
if (valid) return idx; if (valid) return idx;
else return -1; else return -1;
} }
void cmdFatal(char *fmt, ...)
{
char buf[128];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
fprintf(stderr, "%s\n", buf);
fflush(stderr);
exit(EXIT_FAILURE);
}
char * cmdErrStr(int error) char * cmdErrStr(int error)
{ {
int i; int i;

View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 7+ This version is for pigpio version 11+
*/ */
#ifndef COMMAND_H #ifndef COMMAND_H
@ -43,16 +43,17 @@ typedef struct
char * name; /* command name */ char * name; /* command name */
int vt; /* command verification type */ int vt; /* command verification type */
int rv; /* command return value type */ int rv; /* command return value type */
int ext; /* command has extensions */
} cmdInfo_t; } cmdInfo_t;
extern cmdInfo_t cmdInfo[]; extern cmdInfo_t cmdInfo[];
extern char * cmdUsage; extern char * cmdUsage;
int cmdParse(char * buf, cmdCmd_t * cmd); int cmdParse
(char *buf, cmdCmd_t *cmd, int argc, char *argv[], gpioExtent_t * ext);
char * cmdErrStr(int error); char * cmdErrStr(int error);
void cmdFatal(char *fmt, ...);
#endif #endif

602
pigpio.c
View File

@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/> For more information, please refer to <http://unlicense.org/>
*/ */
/* pigpio version 10 */ /* pigpio version 11 */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -752,7 +752,7 @@ static int wfcur=0;
static wfStats_t wfStats= static wfStats_t wfStats=
{ {
0, 0, -1, 0, 0, PI_WAVE_MAX_MICROS,
0, 0, PI_WAVE_MAX_PULSES, 0, 0, PI_WAVE_MAX_PULSES,
0, 0, (PAGES_PER_BLOCK * CBS_PER_OPAGE) 0, 0, (PAGES_PER_BLOCK * CBS_PER_OPAGE)
}; };
@ -765,7 +765,7 @@ static volatile uint32_t notifyBits = 0;
static volatile int DMAstarted = 0; static volatile int DMAstarted = 0;
static int libInitialised = 0; static int libInitialised = 0;
static int pthAlertRunning = 0; static int pthAlertRunning = 0;
static int pthFifoRunning = 0; static int pthFifoRunning = 0;
@ -881,7 +881,7 @@ static uint32_t myGpioDelay(uint32_t micros)
start = systReg[SYST_CLO]; start = systReg[SYST_CLO];
if (micros < 100) while ((systReg[SYST_CLO] - start) <= micros) ; if (micros < 101) while ((systReg[SYST_CLO] - start) <= micros) ;
else myGpioSleep(micros/MILLION, micros%MILLION); else myGpioSleep(micros/MILLION, micros%MILLION);
@ -977,104 +977,19 @@ static uint32_t myGetTick(int pos)
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static void myDoCommand(cmdCmd_t * cmd) static void myDoCommand(cmdCmd_t *cmd, gpioExtent_t *ext)
{ {
int p1, p2, res; int p1, p2, res, i;
uint32_t mask; uint32_t mask, tmp;
gpioPulse_t *pulse;
int masked;
p1 = cmd->p1; p1 = cmd->p1;
p2 = cmd->p2; p2 = cmd->p2;
res = cmd->res;
res = 0;
switch (cmd->cmd) switch (cmd->cmd)
{ {
case PI_CMD_MODES:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetMode(p1, p2);
else
{
PERM_ERROR("gpioSetMode: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break;
case PI_CMD_MODEG:
res = gpioGetMode(p1);
break;
case PI_CMD_PUD:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPullUpDown(p1, p2);
else
{
PERM_ERROR(
"gpioSetPullUpDown: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break;
case PI_CMD_READ:
res = gpioRead(p1);
break;
case PI_CMD_WRITE:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioWrite(p1, p2);
else
{
PERM_ERROR("gpioWrite: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break;
case PI_CMD_PWM:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioPWM(p1, p2);
else
{
PERM_ERROR("gpioPWM: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break;
case PI_CMD_PRS:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMrange(p1, p2);
else
{
PERM_ERROR(
"gpioSetPWMrange: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break;
case PI_CMD_PFS:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMfrequency(p1, p2);
else
{
PERM_ERROR(
"gpioSetPWMfrequency: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break;
case PI_CMD_SERVO:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioServo(p1, p2);
else
{
PERM_ERROR("gpioServo: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break;
case PI_CMD_WDOG:
res = gpioSetWatchdog(p1, p2);
break;
case PI_CMD_BR1:
res = gpioRead_Bits_0_31();
break;
case PI_CMD_BR2:
res = gpioRead_Bits_32_53();
break;
case PI_CMD_BC1: case PI_CMD_BC1:
mask = gpioMask; mask = gpioMask;
@ -1103,6 +1018,10 @@ static void myDoCommand(cmdCmd_t * cmd)
} }
break; break;
case PI_CMD_BR1: res = gpioRead_Bits_0_31(); break;
case PI_CMD_BR2: res = gpioRead_Bits_32_53(); break;
case PI_CMD_BS1: case PI_CMD_BS1:
mask = gpioMask; mask = gpioMask;
@ -1131,52 +1050,209 @@ static void myDoCommand(cmdCmd_t * cmd)
} }
break; break;
case PI_CMD_TICK: case PI_CMD_HELP: break;
res = gpioTick();
case PI_CMD_HWVER: res = gpioHardwareRevision(); break;
case PI_CMD_MODEG: res = gpioGetMode(p1); break;
case PI_CMD_MODES:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetMode(p1, p2);
else
{
PERM_ERROR("gpioSetMode: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break; break;
case PI_CMD_HWVER: case PI_CMD_NB: res = gpioNotifyBegin(p1, p2); break;
res = gpioHardwareRevision();
case PI_CMD_NC: res = gpioNotifyClose(p1); break;
case PI_CMD_NO: res = gpioNotifyOpen(); break;
case PI_CMD_NP: res = gpioNotifyPause(p1); break;
case PI_CMD_PFG: res = gpioGetPWMfrequency(p1); break;
case PI_CMD_PFS:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMfrequency(p1, p2);
else
{
PERM_ERROR(
"gpioSetPWMfrequency: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break; break;
case PI_CMD_PRG: case PI_CMD_PIGPV: res = gpioVersion(); break;
res = gpioGetPWMrange(p1);
case PI_CMD_PRG: res = gpioGetPWMrange(p1); break;
case PI_CMD_PROC:
res = gpioStoreScript(ext[0].ptr);
break; break;
case PI_CMD_PFG: case PI_CMD_PROCD: res = gpioDeleteScript(p1); break;
res = gpioGetPWMfrequency(p1);
case PI_CMD_PROCR: res = gpioRunScript(p1); break;
case PI_CMD_PROCS: res = gpioStopScript(p1); break;
case PI_CMD_PRRG: res = gpioGetPWMrealRange(p1); break;
case PI_CMD_PRS:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMrange(p1, p2);
else
{
PERM_ERROR(
"gpioSetPWMrange: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break; break;
case PI_CMD_PRRG: case PI_CMD_PUD:
res = gpioGetPWMrealRange(p1); if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPullUpDown(p1, p2);
else
{
PERM_ERROR(
"gpioSetPullUpDown: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break; break;
case PI_CMD_NO: case PI_CMD_PWM:
res = gpioNotifyOpen(); if (gpioMask & (uint64_t)(1<<p1)) res = gpioPWM(p1, p2);
else
{
PERM_ERROR("gpioPWM: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break; break;
case PI_CMD_NB: case PI_CMD_READ: res = gpioRead(p1); break;
res = gpioNotifyBegin(p1, p2);
case PI_CMD_WDOG: res = gpioSetWatchdog(p1, p2); break;
case PI_CMD_WRITE:
if (gpioMask & (uint64_t)(1<<p1)) res = gpioWrite(p1, p2);
else
{
PERM_ERROR("gpioWrite: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break; break;
case PI_CMD_NP: case PI_CMD_SERVO:
res = gpioNotifyPause(p1); if (gpioMask & (uint64_t)(1<<p1)) res = gpioServo(p1, p2);
else
{
PERM_ERROR("gpioServo: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break; break;
case PI_CMD_NC: case PI_CMD_TICK: res = gpioTick(); break;
res = gpioNotifyClose(p1);
case PI_CMD_TRIG:
if (gpioMask & (uint64_t)(1<<p1))
res = gpioTrigger(p1, p2, *(int *) (ext[0].ptr));
else
{
PERM_ERROR("gpioTrigger: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break; break;
case PI_CMD_HELP: case PI_CMD_WVAG:
/* need to mask off any non permitted gpios */
mask = gpioMask;
pulse = ext[0].ptr;
masked = 0;
for (i=0; i<p1; i++)
{
tmp = pulse[i].gpioOn & mask;
if (tmp != pulse[i].gpioOn)
{
pulse[i].gpioOn = tmp;
masked = 1;
}
tmp = pulse[i].gpioOff & mask;
if (tmp != pulse[i].gpioOff)
{
pulse[i].gpioOff = tmp;
masked = 1;
}
}
res = gpioWaveAddGeneric(p1, pulse);
/* report permission error unless another error occurred */
if (masked && (res >= 0)) res = PI_SOME_PERMITTED;
break; break;
case PI_CMD_PIGPV: case PI_CMD_WVAS:
res = gpioVersion(); if (gpioMask & (uint64_t)(1<<p1))
res = gpioWaveAddSerial
(p1,
*(int *)(ext[0].ptr),
*(int *)(ext[1].ptr),
p2,
ext[2].ptr);
else
{
PERM_ERROR
("gpioWaveAddSerial: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED;
}
break; break;
} case PI_CMD_WVBSY: res = gpioWaveTxBusy(); break;
cmd->res = res; case PI_CMD_WVCLR: res = gpioWaveClear(); break;
case PI_CMD_WVGO: res = gpioWaveTxStart(PI_WAVE_MODE_ONE_SHOT); break;
case PI_CMD_WVGOR: res = gpioWaveTxStart(PI_WAVE_MODE_REPEAT); break;
case PI_CMD_WVHLT: res = gpioWaveTxStop(); break;
case PI_CMD_WVSC:
switch(p1)
{
case 0: res = gpioWaveGetCbs(); break;
case 1: res = gpioWaveGetHighCbs(); break;
case 2: res = gpioWaveGetMaxCbs(); break;
default: res = -9999;
}
break;
case PI_CMD_WVSM:
switch(p1)
{
case 0: res = gpioWaveGetMicros(); break;
case 1: res = gpioWaveGetHighMicros(); break;
case 2: res = gpioWaveGetMaxMicros(); break;
default: res = -9999;
}
break;
case PI_CMD_WVSP:
switch(p1)
{
case 0: res = gpioWaveGetPulses(); break;
case 1: res = gpioWaveGetHighPulses(); break;
case 2: res = gpioWaveGetMaxPulses(); break;
default: res = -9999;
}
break;
}
cmd->res = res;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
@ -2545,9 +2621,10 @@ static void * pthTimerTick(void *x)
static void * pthFifoThread(void *x) static void * pthFifoThread(void *x)
{ {
char inBuf[128]; char inBuf[256];
int idx, flags; int idx, flags;
cmdCmd_t cmd; cmdCmd_t cmd;
gpioExtent_t ext[3];
myCreatePipe(PI_INPFIFO, 0662); myCreatePipe(PI_INPFIFO, 0662);
@ -2569,9 +2646,9 @@ static void * pthFifoThread(void *x)
if (fgets(inBuf, sizeof(inBuf), inpFifo) == NULL) if (fgets(inBuf, sizeof(inBuf), inpFifo) == NULL)
SOFT_ERROR((void*)PI_INIT_FAILED, "fifo fgets failed (%m)"); SOFT_ERROR((void*)PI_INIT_FAILED, "fifo fgets failed (%m)");
if ((idx=cmdParse(inBuf, &cmd)) >= 0) if ((idx=cmdParse(inBuf, &cmd, 0, NULL, ext)) >= 0)
{ {
myDoCommand(&cmd); myDoCommand(&cmd, NULL);
switch (cmdInfo[idx].rv) switch (cmdInfo[idx].rv)
{ {
@ -2611,24 +2688,150 @@ static void * pthFifoThread(void *x)
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static void * pthSocketThreadHandler(void *fdC) static void *pthSocketThreadHandler(void *fdC)
{ {
int sock = *(int*)fdC; int sock = *(int*)fdC;
cmdCmd_t cmd; cmdCmd_t cmd;
unsigned bytes;
char *memPtr;
gpioExtent_t ext[3];
unsigned tmp;
free(fdC); free(fdC);
while(1) while(1)
{ {
if (recv(sock, &cmd, sizeof(cmdCmd_t), 0) == sizeof(cmdCmd_t)) if (recv(sock, &cmd, sizeof(cmdCmd_t), MSG_WAITALL) == sizeof(cmdCmd_t))
{ {
if (cmd.cmd != PI_CMD_NOIB) if (cmd.cmd == PI_CMD_NOIB)
{ {
myDoCommand(&cmd); cmd.res = gpioNotifyOpenInBand(sock);
}
else if (cmd.cmd == PI_CMD_WVAG)
{
/*
p1=numPulses
p2=0
## extension ##
gpioPulse_t[] pulses
*/
bytes = cmd.p1 * sizeof(gpioPulse_t);
memPtr = malloc(bytes);
if (memPtr)
{
if (recv(sock, memPtr, bytes, MSG_WAITALL) == bytes)
{
ext[0].n = bytes;
ext[0].ptr = memPtr;
myDoCommand(&cmd, ext);
free(memPtr);
}
else
{
free(memPtr);
break;
}
}
else break;
}
else if (cmd.cmd == PI_CMD_WVAS)
{
/*
p1=user_gpio
p2=numChar
## extension ##
unsigned baud
unsigned offset
char[] str
*/
bytes = sizeof(unsigned) + sizeof(unsigned) + cmd.p2;
memPtr = malloc(bytes+1); /* add 1 for a nul terminator */
if (memPtr)
{
if (recv(sock, memPtr, bytes, MSG_WAITALL) == bytes)
{
ext[0].n = sizeof(unsigned);
ext[0].ptr = memPtr;
ext[1].n = sizeof(unsigned);
ext[1].ptr = memPtr + sizeof(unsigned);
ext[2].n = cmd.p2;
ext[2].ptr = memPtr + sizeof(unsigned) + sizeof(unsigned);
memPtr[bytes] = 0; /* may be duplicate terminator */
myDoCommand(&cmd, ext);
free(memPtr);
}
else
{
free(memPtr);
break;
}
}
else break;
}
else if (cmd.cmd == PI_CMD_PROC)
{
/*
p1=script length
p2=0
## extension ##
char[] script
*/
bytes = cmd.p1;
memPtr = malloc(bytes+1); /* add 1 for a nul terminator */
if (memPtr)
{
if (recv(sock, memPtr, bytes, MSG_WAITALL) == bytes)
{
ext[0].n = bytes;
ext[0].ptr = memPtr;
memPtr[bytes] = 0; /* may be duplicate terminator */
myDoCommand(&cmd, ext);
free(memPtr);
}
else
{
free(memPtr);
break;
}
}
else break;
} }
else else
{ {
cmd.res = gpioNotifyOpenInBand(sock); switch (cmd.cmd)
{
case PI_CMD_TRIG:
/*
p1=user_gpio
p2=pulseLen
## extension ##
unsigned level
*/
ext[0].n = 4;
ext[0].ptr = &tmp;
if (recv(sock, &tmp, sizeof(unsigned), MSG_WAITALL) !=
sizeof(unsigned))
{
close(sock);
return 0;
}
break;
default:
break;
}
myDoCommand(&cmd, ext);
} }
write(sock, &cmd, sizeof(cmdCmd_t)); write(sock, &cmd, sizeof(cmdCmd_t));
@ -2647,10 +2850,8 @@ static void * pthSocketThreadHandler(void *fdC)
static void * pthSocketThread(void *x) static void * pthSocketThread(void *x)
{ {
int fdC, c, *sock; int fdC, c, *sock;
struct sockaddr_in server, client; struct sockaddr_in client;
pthread_attr_t attr; pthread_attr_t attr;
char * portStr;
unsigned port;
if (pthread_attr_init(&attr)) if (pthread_attr_init(&attr))
SOFT_ERROR((void*)PI_INIT_FAILED, SOFT_ERROR((void*)PI_INIT_FAILED,
@ -2664,21 +2865,8 @@ static void * pthSocketThread(void *x)
SOFT_ERROR((void*)PI_INIT_FAILED, SOFT_ERROR((void*)PI_INIT_FAILED,
"pthread_attr_setdetachstate failed (%m)"); "pthread_attr_setdetachstate failed (%m)");
fdSock = socket(AF_INET , SOCK_STREAM , 0); /* fdSock opened in gpioInitialise so that we can treat
failure to bind as fatal. */
if (fdSock == -1)
SOFT_ERROR((void*)PI_INIT_FAILED, "socket failed (%m)");
portStr = getenv(PI_ENVPORT);
if (portStr) port = atoi(portStr); else port = gpioCfg.socketPort;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
if (bind(fdSock,(struct sockaddr *)&server , sizeof(server)) < 0)
SOFT_ERROR((void*)PI_INIT_FAILED, "bind failed (%m)");
listen(fdSock, 100); listen(fdSock, 100);
@ -3264,7 +3452,7 @@ static void initClearGlobals(void)
wfStats.micros = 0; wfStats.micros = 0;
wfStats.highMicros = 0; wfStats.highMicros = 0;
wfStats.maxMicros = -1; wfStats.maxMicros = PI_WAVE_MAX_MICROS;
wfStats.pulses = 0; wfStats.pulses = 0;
wfStats.highPulses = 0; wfStats.highPulses = 0;
@ -3406,7 +3594,8 @@ static void initReleaseResources(void)
munmap(dmaVirt[i], PAGE_SIZE); munmap(dmaVirt[i], PAGE_SIZE);
} }
munmap(dmaVirt, PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *)); munmap(dmaVirt,
PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *));
} }
dmaVirt = MAP_FAILED; dmaVirt = MAP_FAILED;
@ -3418,7 +3607,8 @@ static void initReleaseResources(void)
munmap(dmaPhys[i], PAGE_SIZE); munmap(dmaPhys[i], PAGE_SIZE);
} }
munmap(dmaPhys, PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *)); munmap(dmaPhys,
PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *));
} }
dmaPhys = MAP_FAILED; dmaPhys = MAP_FAILED;
@ -3474,6 +3664,9 @@ static void initReleaseResources(void)
int gpioInitialise(void) int gpioInitialise(void)
{ {
int i; int i;
struct sockaddr_in server;
char * portStr;
unsigned port;
clock_gettime(CLOCK_REALTIME, &libStarted); clock_gettime(CLOCK_REALTIME, &libStarted);
@ -3542,6 +3735,22 @@ int gpioInitialise(void)
if (!(gpioCfg.ifFlags & PI_DISABLE_SOCK_IF)) if (!(gpioCfg.ifFlags & PI_DISABLE_SOCK_IF))
{ {
fdSock = socket(AF_INET , SOCK_STREAM , 0);
if (fdSock == -1)
SOFT_ERROR(PI_INIT_FAILED, "socket failed (%m)");
portStr = getenv(PI_ENVPORT);
if (portStr) port = atoi(portStr); else port = gpioCfg.socketPort;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
if (bind(fdSock,(struct sockaddr *)&server , sizeof(server)) < 0)
SOFT_ERROR(PI_INIT_FAILED, "bind to port %d failed (%m)", port);
if (pthread_create(&pthSocket, &pthAttr, pthSocketThread, &i)) if (pthread_create(&pthSocket, &pthAttr, pthSocketThread, &i))
SOFT_ERROR(PI_INIT_FAILED, "pthread_create socket failed (%m)"); SOFT_ERROR(PI_INIT_FAILED, "pthread_create socket failed (%m)");
@ -4127,15 +4336,16 @@ int gpioWaveAddGeneric(unsigned numPulses, gpioPulse_t * pulses)
int gpioWaveAddSerial(unsigned gpio, int gpioWaveAddSerial(unsigned gpio,
unsigned baud, unsigned baud,
unsigned offset,
unsigned numChar, unsigned numChar,
char * str) char *str)
{ {
int i, b, p, lev, c, v; int i, b, p, lev, c, v;
unsigned bitDelay[10]; unsigned bitDelay[10];
DBG(DBG_USER, "gpio=%d baud=%d numChar=%d str*=%08X", DBG(DBG_USER, "gpio=%d baud=%d offset=%d numChar=%d str=%s",
gpio, baud, numChar, (uint32_t)str); gpio, baud, offset, numChar, str);
CHECK_INITED; CHECK_INITED;
@ -4149,6 +4359,9 @@ int gpioWaveAddSerial(unsigned gpio,
if (numChar > PI_WAVE_MAX_CHARS) if (numChar > PI_WAVE_MAX_CHARS)
SOFT_ERROR(PI_TOO_MANY_CHARS, "too many chars (%d)", numChar); SOFT_ERROR(PI_TOO_MANY_CHARS, "too many chars (%d)", numChar);
if (offset > PI_WAVE_MAX_MICROS)
SOFT_ERROR(PI_BAD_SER_OFFSET, "offset too large (%d)", offset);
if (!numChar) return 0; if (!numChar) return 0;
waveBitDelay(baud, bitDelay); waveBitDelay(baud, bitDelay);
@ -4157,7 +4370,9 @@ int gpioWaveAddSerial(unsigned gpio,
wf[2][p].gpioOn = (1<<gpio); wf[2][p].gpioOn = (1<<gpio);
wf[2][p].gpioOff = 0; wf[2][p].gpioOff = 0;
wf[2][p].usDelay = bitDelay[0];
if (offset > bitDelay[0]) wf[2][p].usDelay = offset;
else wf[2][p].usDelay = bitDelay[0];
for (i=0; i<numChar; i++) for (i=0; i<numChar; i++)
{ {
@ -4609,6 +4824,35 @@ int gpioNotifyClose(unsigned handle)
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */
int gpioTrigger(unsigned gpio, unsigned pulseLen, unsigned level)
{
DBG(DBG_USER, "gpio=%d pulseLen=%d level=%d", gpio, pulseLen, level);
CHECK_INITED;
if (gpio > PI_MAX_USER_GPIO)
SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
if (level > PI_ON)
SOFT_ERROR(PI_BAD_LEVEL, "gpio %d, bad level (%d)", gpio, level);
if (pulseLen > PI_MAX_PULSELEN)
SOFT_ERROR(PI_BAD_PULSELEN,
"gpio %d, bad pulseLen (%d)", gpio, pulseLen);
if (level == PI_OFF) *(gpioReg + GPCLR0 + BANK) = BIT;
else *(gpioReg + GPSET0 + BANK) = BIT;
myGpioDelay(pulseLen);
if (level != PI_OFF) *(gpioReg + GPCLR0 + BANK) = BIT;
else *(gpioReg + GPSET0 + BANK) = BIT;
return 0;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
@ -4769,7 +5013,7 @@ int gpioSetTimerFuncEx(unsigned id, unsigned ms, gpioTimerFuncEx_t f,
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
pthread_t *gpioStartThread(ThreadFunc_t func, void *arg) pthread_t *gpioStartThread(gpioThreadFunc_t func, void *arg)
{ {
pthread_t *pth; pthread_t *pth;
pthread_attr_t pthAttr; pthread_attr_t pthAttr;
@ -4818,6 +5062,58 @@ void gpioStopThread(pthread_t *pth)
} }
} }
/* ----------------------------------------------------------------------- */
int gpioStoreScript(char *script)
{
DBG(DBG_USER, "script=%s", script);
CHECK_INITED;
return PI_BAD_SCRIPT;
}
/* ----------------------------------------------------------------------- */
int gpioRunScript(int script_id)
{
DBG(DBG_USER, "script_id=%d", script_id);
CHECK_INITED;
return PI_BAD_SCRIPT_ID;
}
/* ----------------------------------------------------------------------- */
int gpioStopScript(int script_id)
{
DBG(DBG_USER, "script_id=%d", script_id);
CHECK_INITED;
return PI_BAD_SCRIPT_ID;
}
/* ----------------------------------------------------------------------- */
int gpioDeleteScript(int script_id)
{
DBG(DBG_USER, "script_id=%d", script_id);
CHECK_INITED;
return PI_BAD_SCRIPT_ID;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
int gpioSetSignalFunc(unsigned signum, gpioSignalFunc_t f) int gpioSetSignalFunc(unsigned signum, gpioSignalFunc_t f)

114
pigpio.h
View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 10 This version is for pigpio version 11
*/ */
#ifndef PIGPIO_H #ifndef PIGPIO_H
@ -86,7 +86,7 @@ This version is for pigpio version 10
#include <stdint.h> #include <stdint.h>
#include <pthread.h> #include <pthread.h>
#define PIGPIO_VERSION 10 #define PIGPIO_VERSION 11
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -148,6 +148,8 @@ gpioWaveGetCbs Length in cbs of the current waveform.
gpioWaveGetHighCbs Length of longest waveform so far. gpioWaveGetHighCbs Length of longest waveform so far.
gpioWaveGetMaxCbs Absolute maximum allowed cbs. gpioWaveGetMaxCbs Absolute maximum allowed cbs.
gpioTrigger Send a trigger pulse to a gpio.
gpioSetWatchdog Set a watchdog on a gpio. gpioSetWatchdog Set a watchdog on a gpio.
gpioSetGetSamplesFunc Requests a gpio samples callback. gpioSetGetSamplesFunc Requests a gpio samples callback.
@ -159,6 +161,11 @@ gpioSetTimerFuncEx Request a regular timed callback, extended.
gpioStartThread Start a new thread. gpioStartThread Start a new thread.
gpioStopThread Stop a previously started thread. gpioStopThread Stop a previously started thread.
gpioStoreScript Store a script.
gpioRunScript Run a stored script.
gpioStopScript Stop a running script.
gpioDeleteScript Delete a stored script.
gpioSetSignalFunc Request a signal callback. gpioSetSignalFunc Request a signal callback.
gpioSetSignalFuncEx Request a signal callback, extended. gpioSetSignalFuncEx Request a signal callback, extended.
@ -217,6 +224,13 @@ typedef struct
uint32_t res; uint32_t res;
} cmdCmd_t; } cmdCmd_t;
typedef struct
{
size_t n;
void *ptr;
int data;
} gpioExtent_t;
typedef struct typedef struct
{ {
uint32_t tick; uint32_t tick;
@ -271,8 +285,7 @@ typedef void (*gpioGetSamplesFuncEx_t) (const gpioSample_t * samples,
int numSamples, int numSamples,
void * userdata); void * userdata);
typedef void *(ThreadFunc_t) (void *); typedef void *(gpioThreadFunc_t) (void *);
/* /*
@ -881,7 +894,6 @@ int gpioWaveAddGeneric(unsigned numPulses, gpioPulse_t * pulses);
If the added waveform is intended to start after or within the existing If the added waveform is intended to start after or within the existing
waveform then the first pulse should consist of a delay. waveform then the first pulse should consist of a delay.
*/ */
@ -889,15 +901,17 @@ int gpioWaveAddGeneric(unsigned numPulses, gpioPulse_t * pulses);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int gpioWaveAddSerial(unsigned user_gpio, int gpioWaveAddSerial(unsigned user_gpio,
unsigned baud, unsigned baud,
unsigned offset,
unsigned numChar, unsigned numChar,
char * str); char * str);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* This function adds a waveform representing serial data to the /* This function adds a waveform representing serial data to the
existing waveform (if any). existing waveform (if any). The serial data starts offset microseconds
from the start of the waveform.
Returns the new total number of pulses in the current waveform if OK, Returns the new total number of pulses in the current waveform if OK,
otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_TOO_MANY_CHARS, or otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_TOO_MANY_CHARS,
PI_TOO_MANY_PULSES. PI_BAD_SER_OFFSET, or PI_TOO_MANY_PULSES.
NOTES: NOTES:
@ -915,6 +929,8 @@ int gpioWaveAddSerial(unsigned user_gpio,
#define PI_WAVE_MIN_BAUD 100 #define PI_WAVE_MIN_BAUD 100
#define PI_WAVE_MAX_BAUD 250000 #define PI_WAVE_MAX_BAUD 250000
#define PI_WAVE_MAX_MICROS (30 * 60 * 1000000) /* half an hour */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -923,7 +939,8 @@ int gpioWaveTxStart(unsigned mode);
/* This function transmits the current waveform. The mode determines /* This function transmits the current waveform. The mode determines
whether the waveform is sent once or cycles endlessly. whether the waveform is sent once or cycles endlessly.
Returns 0 if OK, otherwise PI_BAD_WAVE_MODE. Returns the number of DMA control blocks in the waveform if OK,
otherwise PI_BAD_WAVE_MODE.
*/ */
#define PI_WAVE_MODE_ONE_SHOT 0 #define PI_WAVE_MODE_ONE_SHOT 0
@ -1112,6 +1129,19 @@ int gpioWaveGetMaxCbs(void);
/*-------------------------------------------------------------------------*/
int gpioTrigger(unsigned user_gpio, unsigned pulseLen, unsigned level);
/*-------------------------------------------------------------------------*/
/* This function sends a trigger pulse to a gpio. The gpio is set to
level for pulseLen microseconds and then reset to not level.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_LEVEL,
or PI_BAD_PULSELEN.
*/
#define PI_MAX_PULSELEN 100
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int gpioSetWatchdog(unsigned user_gpio, int gpioSetWatchdog(unsigned user_gpio,
unsigned timeout); unsigned timeout);
@ -1267,7 +1297,7 @@ int gpioSetTimerFuncEx(unsigned timer,
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
pthread_t *gpioStartThread(ThreadFunc_t func, void *arg); pthread_t *gpioStartThread(gpioThreadFunc_t func, void *arg);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* Starts a new thread of execution with func as the main routine. /* Starts a new thread of execution with func as the main routine.
@ -1327,6 +1357,46 @@ void gpioStopThread(pthread_t *pth);
*/ */
/* ----------------------------------------------------------------------- */
int gpioStoreScript(char *script);
/* ----------------------------------------------------------------------- */
/* This function stores a null terminated script for later execution.
The function returns a script id if the script is valid,
otherwise PI_BAD_SCRIPT.
*/
/* ----------------------------------------------------------------------- */
int gpioRunScript(int script_id);
/* ----------------------------------------------------------------------- */
/* This function runs a stored script.
The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
*/
/* ----------------------------------------------------------------------- */
int gpioStopScript(int script_id);
/* ----------------------------------------------------------------------- */
/* This function stops a running script.
The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
*/
/* ----------------------------------------------------------------------- */
int gpioDeleteScript(int script_id);
/* ----------------------------------------------------------------------- */
/* This function deletes a stored script.
The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
*/
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int gpioSetSignalFunc(unsigned signum, int gpioSetSignalFunc(unsigned signum,
@ -1816,6 +1886,21 @@ void gpioWaveDump(void);
#define PI_CMD_PRRG 24 #define PI_CMD_PRRG 24
#define PI_CMD_HELP 25 #define PI_CMD_HELP 25
#define PI_CMD_PIGPV 26 #define PI_CMD_PIGPV 26
#define PI_CMD_WVCLR 27
#define PI_CMD_WVAG 28
#define PI_CMD_WVAS 29
#define PI_CMD_WVGO 30
#define PI_CMD_WVGOR 31
#define PI_CMD_WVBSY 32
#define PI_CMD_WVHLT 33
#define PI_CMD_WVSM 34
#define PI_CMD_WVSP 35
#define PI_CMD_WVSC 36
#define PI_CMD_TRIG 37
#define PI_CMD_PROC 38
#define PI_CMD_PROCD 39
#define PI_CMD_PROCR 40
#define PI_CMD_PROCS 41
/* /*
The following command only works on the socket interface. The following command only works on the socket interface.
@ -1841,7 +1926,7 @@ after this command is issued.
#define PI_BAD_LEVEL -5 /* level not 0-1 */ #define PI_BAD_LEVEL -5 /* level not 0-1 */
#define PI_BAD_PUD -6 /* pud not 0-2 */ #define PI_BAD_PUD -6 /* pud not 0-2 */
#define PI_BAD_PULSEWIDTH -7 /* pulsewidth not 0 or 500-2500 */ #define PI_BAD_PULSEWIDTH -7 /* pulsewidth not 0 or 500-2500 */
#define PI_BAD_DUTYCYCLE -8 /* dutycycle not 0-255 */ #define PI_BAD_DUTYCYCLE -8 /* dutycycle outside set range */
#define PI_BAD_TIMER -9 /* timer not 0-9 */ #define PI_BAD_TIMER -9 /* timer not 0-9 */
#define PI_BAD_MS -10 /* ms not 10-60000 */ #define PI_BAD_MS -10 /* ms not 10-60000 */
#define PI_BAD_TIMETYPE -11 /* timetype not 0-1 */ #define PI_BAD_TIMETYPE -11 /* timetype not 0-1 */
@ -1878,6 +1963,13 @@ after this command is issued.
#define PI_BAD_SERIAL_BUF -40 /* bad (null) serial buf parameter */ #define PI_BAD_SERIAL_BUF -40 /* bad (null) serial buf parameter */
#define PI_NOT_PERMITTED -41 /* gpio operation not permitted */ #define PI_NOT_PERMITTED -41 /* gpio operation not permitted */
#define PI_SOME_PERMITTED -42 /* one or more gpios not permitted */ #define PI_SOME_PERMITTED -42 /* one or more gpios not permitted */
#define PI_BAD_WVSC_COMMND -43 /* bad WVSC subcommand */
#define PI_BAD_WVSM_COMMND -44 /* bad WVSM subcommand */
#define PI_BAD_WVSP_COMMND -45 /* bad WVSP subcommand */
#define PI_BAD_PULSELEN -46 /* trigger pulse length > 100 */
#define PI_BAD_SCRIPT -47 /* invalid script */
#define PI_BAD_SCRIPT_ID -48 /* unknown script id */
#define PI_BAD_SER_OFFSET -49 /* add serial data offset > 30 minutes */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/

526
pigpio.py
View File

@ -76,7 +76,7 @@ import threading
import os import os
import atexit import atexit
VERSION = "1.1" VERSION = "1.2"
# gpio levels # gpio levels
@ -140,8 +140,28 @@ _PI_CMD_NC= 21
_PI_CMD_PRG= 22 _PI_CMD_PRG= 22
_PI_CMD_PFG= 23 _PI_CMD_PFG= 23
_PI_CMD_PRRG= 24 _PI_CMD_PRRG= 24
_PI_CMD_HELP= 25
_PI_CMD_PIGPV=26
_PI_CMD_WVCLR=27
_PI_CMD_WVAG= 28
_PI_CMD_WVAS= 29
_PI_CMD_WVGO= 30
_PI_CMD_WVGOR=31
_PI_CMD_WVBSY=32
_PI_CMD_WVHLT=33
_PI_CMD_WVSM= 34
_PI_CMD_WVSP= 35
_PI_CMD_WVSC= 36
_PI_CMD_TRIG= 37
_PI_CMD_PROC= 38
_PI_CMD_PROCD=39
_PI_CMD_PROCR=40
_PI_CMD_PROCS=41
_PI_CMD_NOIB= 99 _PI_CMD_NOIB= 99
# pigpio error numbers # pigpio error numbers
_PI_INIT_FAILED =-1 _PI_INIT_FAILED =-1
@ -179,14 +199,21 @@ _PI_NOT_INITIALISED =-31
_PI_INITIALISED =-32 _PI_INITIALISED =-32
_PI_BAD_WAVE_MODE =-33 _PI_BAD_WAVE_MODE =-33
_PI_BAD_CFG_INTERNAL=-34 _PI_BAD_CFG_INTERNAL=-34
_PI_BAD_WAVE_BAUD =-35 PI_BAD_WAVE_BAUD =-35
_PI_TOO_MANY_PULSES =-36 PI_TOO_MANY_PULSES =-36
_PI_TOO_MANY_CHARS =-37 PI_TOO_MANY_CHARS =-37
_PI_NOT_SERIAL_GPIO =-38 _PI_NOT_SERIAL_GPIO =-38
_PI_BAD_SERIAL_STRUC=-39 _PI_BAD_SERIAL_STRUC=-39
_PI_BAD_SERIAL_BUF =-40 _PI_BAD_SERIAL_BUF =-40
PI_NOT_PERMITTED =-41 PI_NOT_PERMITTED =-41
PI_SOME_PERMITTED =-42 PI_SOME_PERMITTED =-42
PI_BAD_WVSC_COMMND =-43
PI_BAD_WVSM_COMMND =-44
PI_BAD_WVSP_COMMND =-45
PI_BAD_PULSELEN =-46
PI_BAD_SCRIPT =-47
PI_BAD_SCRIPT_ID =-48
PI_BAD_SER_OFFSET =-49
# pigpio error text # pigpio error text
@ -225,12 +252,19 @@ _errors=[
[_PI_INITIALISED , "function called after gpioInitialise"], [_PI_INITIALISED , "function called after gpioInitialise"],
[_PI_BAD_WAVE_MODE , "waveform mode not 0-1"], [_PI_BAD_WAVE_MODE , "waveform mode not 0-1"],
[_PI_BAD_CFG_INTERNAL , "bad parameter in gpioCfgInternals call"], [_PI_BAD_CFG_INTERNAL , "bad parameter in gpioCfgInternals call"],
[_PI_BAD_WAVE_BAUD , "baud rate not 100-250000"], [PI_BAD_WAVE_BAUD , "baud rate not 100-250000"],
[_PI_TOO_MANY_PULSES , "waveform has too many pulses"], [PI_TOO_MANY_PULSES , "waveform has too many pulses"],
[_PI_TOO_MANY_CHARS , "waveform has too many chars"], [PI_TOO_MANY_CHARS , "waveform has too many chars"],
[_PI_NOT_SERIAL_GPIO , "no serial read in progress on gpio"], [_PI_NOT_SERIAL_GPIO , "no serial read in progress on gpio"],
[PI_NOT_PERMITTED , "no permission to update gpio"], [PI_NOT_PERMITTED , "no permission to update gpio"],
[PI_SOME_PERMITTED , "no permission to update one or more gpios"] [PI_SOME_PERMITTED , "no permission to update one or more gpios"],
[PI_BAD_WVSC_COMMND , "bad WVSC subcommand"],
[PI_BAD_WVSM_COMMND , "bad WVSM subcommand"],
[PI_BAD_WVSP_COMMND , "bad WVSP subcommand"],
[PI_BAD_PULSELEN , "trigger pulse length > 100"],
[PI_BAD_SCRIPT , "invalid script"],
[PI_BAD_SCRIPT_ID , "unknown script id"],
[PI_BAD_SER_OFFSET , "add serial data offset > 30 minute"],
] ]
_control = None _control = None
@ -262,7 +296,7 @@ def error(pigpio_error):
for e in _errors: for e in _errors:
if e[0] == pigpio_error: if e[0] == pigpio_error:
return e[1] return e[1]
return "unknown error" return "unknown error ({})".format(pigpio_error)
def tickDiff(tStart, tEnd): def tickDiff(tStart, tEnd):
"""Calculate the time difference between two ticks. """Calculate the time difference between two ticks.
@ -304,7 +338,8 @@ def _u2i(number):
return v return v
def _pigpio_command(sock, cmd, p1, p2): def _pigpio_command(sock, cmd, p1, p2):
"""Executes a pigpio socket command. """
Executes a pigpio socket command.
sock: command socket. sock: command socket.
cmd: the command to be executed. cmd: the command to be executed.
@ -318,6 +353,27 @@ def _pigpio_command(sock, cmd, p1, p2):
else: else:
raise _pigpioError("*** Module not started, call pigpio.start() ***") raise _pigpioError("*** Module not started, call pigpio.start() ***")
def _pigpio_command_ext(sock, cmd, p1, p2, extents):
"""
Executes an extended pigpio socket command.
sock: command socket.
cmd: the command to be executed.
p1: command paramter 1 (if applicable).
p2: command paramter 2 (if applicable).
extents: additional data blocks
"""
if sock is not None:
sock.send(struct.pack('IIII', cmd, p1, p2, 0))
for ext in extents:
sock.sendall(ext)
x, y, z, res = struct.unpack('IIII', sock.recv(16))
return res
else:
raise _pigpioError("*** Module not started, call pigpio.start() ***")
class _callback: class _callback:
"""An ADT class to hold callback information.""" """An ADT class to hold callback information."""
@ -462,8 +518,7 @@ def set_mode(gpio, mode):
pigpio.set_mode(10, pigpio.ALT2) # gpio 10 as ALT2 pigpio.set_mode(10, pigpio.ALT2) # gpio 10 as ALT2
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_MODES, gpio, mode)) return _u2i(_pigpio_command(_control, _PI_CMD_MODES, gpio, mode))
return r
def get_mode(gpio): def get_mode(gpio):
"""Get the gpio mode. """Get the gpio mode.
@ -482,8 +537,7 @@ def get_mode(gpio):
6 6
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_MODEG, gpio, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_MODEG, gpio, 0))
return r
def set_pull_up_down(gpio, pud): def set_pull_up_down(gpio, pud):
"""Set or clear the gpio pull-up/down resistor. """Set or clear the gpio pull-up/down resistor.
@ -516,8 +570,7 @@ def set_pull_up_down(gpio, pud):
1 1
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_PUD, gpio, pud)) return _u2i(_pigpio_command(_control, _PI_CMD_PUD, gpio, pud))
return r
def read(gpio): def read(gpio):
"""Read the gpio level. """Read the gpio level.
@ -545,8 +598,7 @@ def read(gpio):
1 1
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_READ, gpio, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_READ, gpio, 0))
return r
def write(gpio, level): def write(gpio, level):
"""Write the gpio level. """Write the gpio level.
@ -578,8 +630,7 @@ def write(gpio, level):
1 1
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_WRITE, gpio, level)) return _u2i(_pigpio_command(_control, _PI_CMD_WRITE, gpio, level))
return r
def set_PWM_dutycycle(user_gpio, dutycycle): def set_PWM_dutycycle(user_gpio, dutycycle):
"""Start (non-zero dutycycle) or stop (0) PWM pulses on the gpio. """Start (non-zero dutycycle) or stop (0) PWM pulses on the gpio.
@ -609,8 +660,7 @@ def set_PWM_dutycycle(user_gpio, dutycycle):
set_PWM_dutycycle(4, 255) # PWM full on set_PWM_dutycycle(4, 255) # PWM full on
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_PWM, user_gpio, dutycycle)) return _u2i(_pigpio_command(_control, _PI_CMD_PWM, user_gpio, dutycycle))
return r
def set_PWM_range(user_gpio, range_): def set_PWM_range(user_gpio, range_):
"""Set the range of PWM values to be used on the gpio. """Set the range of PWM values to be used on the gpio.
@ -645,8 +695,7 @@ def set_PWM_range(user_gpio, range_):
pigpio.set_PWM_range(9, 3000) # now 750 1/4, 1500 1/2, 2250 3/4 on pigpio.set_PWM_range(9, 3000) # now 750 1/4, 1500 1/2, 2250 3/4 on
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_PRS, user_gpio, range_)) return _u2i(_pigpio_command(_control, _PI_CMD_PRS, user_gpio, range_))
return r
def get_PWM_range(user_gpio): def get_PWM_range(user_gpio):
"""Get the range of PWM values being used on the gpio. """Get the range of PWM values being used on the gpio.
@ -674,8 +723,7 @@ def get_PWM_range(user_gpio):
3000 3000
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_PRG, user_gpio, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_PRG, user_gpio, 0))
return r
def get_PWM_real_range(user_gpio): def get_PWM_real_range(user_gpio):
"""Get the real underlying range of PWM values being used on the gpio. """Get the real underlying range of PWM values being used on the gpio.
@ -701,8 +749,7 @@ def get_PWM_real_range(user_gpio):
25 25
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_PRRG, user_gpio, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_PRRG, user_gpio, 0))
return r
def set_PWM_frequency(user_gpio, frequency): def set_PWM_frequency(user_gpio, frequency):
"""Set the frequency (in Hz) of the PWM to be used on the gpio. """Set the frequency (in Hz) of the PWM to be used on the gpio.
@ -759,8 +806,7 @@ def set_PWM_frequency(user_gpio, frequency):
8000 8000
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_PFS, user_gpio, frequency)) return _u2i(_pigpio_command(_control, _PI_CMD_PFS, user_gpio, frequency))
return r
def get_PWM_frequency(user_gpio): def get_PWM_frequency(user_gpio):
"""Get the frequency of PWM being used on the gpio. """Get the frequency of PWM being used on the gpio.
@ -788,8 +834,7 @@ def get_PWM_frequency(user_gpio):
8000 8000
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_PFG, user_gpio, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_PFG, user_gpio, 0))
return r
def set_servo_pulsewidth(user_gpio, pulsewidth): def set_servo_pulsewidth(user_gpio, pulsewidth):
"""Start (500-2500) or stop (0) servo pulses on the gpio. """Start (500-2500) or stop (0) servo pulses on the gpio.
@ -845,8 +890,8 @@ def set_servo_pulsewidth(user_gpio, pulsewidth):
for m in moves: for m in moves:
pigpio.set_servo_pulsewidth(24, m[0]); pigpio.set_servo_pulsewidth(24, m[0]);
time.sleep(m[1]) time.sleep(m[1])
message = str(m[1]) + " seconds @ " + str(m[0]) + " us" s = str(m[1]) + " seconds @ " + str(m[0]) + " us"
print(message) print(s)
pigpio.stop() pigpio.stop()
@ -875,8 +920,8 @@ def set_servo_pulsewidth(user_gpio, pulsewidth):
for m in moves: for m in moves:
pigpio.set_PWM_dutycycle(25, m[0]); pigpio.set_PWM_dutycycle(25, m[0]);
time.sleep(m[1]) time.sleep(m[1])
message = str(m[1]) + " seconds @ " + str(m[0]) + " us" s = str(m[1]) + " seconds @ " + str(m[0]) + " us"
print(message) print(s)
pigpio.stop() pigpio.stop()
@ -888,8 +933,7 @@ def set_servo_pulsewidth(user_gpio, pulsewidth):
5 seconds @ 2000 us 5 seconds @ 2000 us
0 seconds @ 1000 us 0 seconds @ 1000 us
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_SERVO, user_gpio, pulsewidth)) return _u2i(_pigpio_command(_control, _PI_CMD_SERVO, user_gpio, pulsewidth))
return r
def notify_open(): def notify_open():
"""Get a free notification handle. """Get a free notification handle.
@ -917,8 +961,7 @@ def notify_open():
pigpio.notify_begin(h, 1234) pigpio.notify_begin(h, 1234)
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_NO, 0, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_NO, 0, 0))
return r
def notify_begin(handle, bits): def notify_begin(handle, bits):
"""Start notifications on a previously opened handle. """Start notifications on a previously opened handle.
@ -951,8 +994,7 @@ def notify_begin(handle, bits):
I (32 bit) level I (32 bit) level
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_NB, handle, bits)) return _u2i(_pigpio_command(_control, _PI_CMD_NB, handle, bits))
return r
def notify_pause(handle): def notify_pause(handle):
"""Pause notifications on a previously opened handle. """Pause notifications on a previously opened handle.
@ -976,8 +1018,7 @@ def notify_pause(handle):
... ...
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_NB, handle, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_NB, handle, 0))
return r
def notify_close(handle): def notify_close(handle):
"""Stop notifications on a previously opened handle and """Stop notifications on a previously opened handle and
@ -997,8 +1038,7 @@ def notify_close(handle):
... ...
... ...
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_NC, handle, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_NC, handle, 0))
return r
def set_watchdog(user_gpio, timeout): def set_watchdog(user_gpio, timeout):
"""Sets a watchdog for a gpio. """Sets a watchdog for a gpio.
@ -1030,8 +1070,8 @@ def set_watchdog(user_gpio, timeout):
import time import time
def cbf(g, L, t): def cbf(g, L, t):
message = "gpio=" + str(g) + " level=" + str(L) + " at " + str(t) s = "gpio=" + str(g) + " level=" + str(L) + " at " + str(t)
print(message) print(s)
pigpio.start() pigpio.start()
@ -1068,8 +1108,7 @@ def set_watchdog(user_gpio, timeout):
gpio=22 level=2 at 3551411622 gpio=22 level=2 at 3551411622
watchdog cancelled, 5 second delay watchdog cancelled, 5 second delay
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_WDOG, user_gpio, timeout)) return _u2i(_pigpio_command(_control, _PI_CMD_WDOG, user_gpio, timeout))
return r
def read_bank_1(): def read_bank_1():
"""Read the levels of the bank 1 gpios (gpios 0-31). """Read the levels of the bank 1 gpios (gpios 0-31).
@ -1148,8 +1187,7 @@ def clear_bank_1(levels):
0b1111110010000 0b1111110010000
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_BC1, levels, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_BC1, levels, 0))
return r
def clear_bank_2(levels): def clear_bank_2(levels):
"""Clears gpios 32-53 if the corresponding bit (0-21) in levels is set. """Clears gpios 32-53 if the corresponding bit (0-21) in levels is set.
@ -1164,8 +1202,7 @@ def clear_bank_2(levels):
See clear_bank_1() for an example. See clear_bank_1() for an example.
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_BC2, levels, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_BC2, levels, 0))
return r
def set_bank_1(levels): def set_bank_1(levels):
"""Sets gpios 0-31 if the corresponding bit in levels is set. """Sets gpios 0-31 if the corresponding bit in levels is set.
@ -1215,8 +1252,7 @@ def set_bank_1(levels):
0b1111111011111 0b1111111011111
0b1111110010000 0b1111110010000
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_BS1, levels, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_BS1, levels, 0))
return r
def set_bank_2(levels): def set_bank_2(levels):
"""Sets gpios 32-53 if the corresponding bit (0-21) in levels is set. """Sets gpios 32-53 if the corresponding bit (0-21) in levels is set.
@ -1231,8 +1267,7 @@ def set_bank_2(levels):
See set_bank_1() for an example. See set_bank_1() for an example.
""" """
r=_u2i(_pigpio_command(_control, _PI_CMD_BS2, levels, 0)) return _u2i(_pigpio_command(_control, _PI_CMD_BS2, levels, 0))
return r
def get_current_tick(): def get_current_tick():
"""Gets the current system tick. """Gets the current system tick.
@ -1257,9 +1292,9 @@ def get_current_tick():
t2 = pigpio.get_current_tick() t2 = pigpio.get_current_tick()
message = "5 seconds is " + str(pigpio.tickDiff(t1, t2)) + " ticks" s = "5 seconds is " + str(pigpio.tickDiff(t1, t2)) + " ticks"
print(message) print(s)
pigpio.stop() pigpio.stop()
@ -1308,6 +1343,365 @@ def get_hardware_revision():
""" """
return _pigpio_command(_control, _PI_CMD_HWVER, 0, 0) return _pigpio_command(_control, _PI_CMD_HWVER, 0, 0)
def get_pigpio_version():
"""
Returns the pigpio software version.
"""
return _pigpio_command(_control, _PI_CMD_PIGPV, 0, 0)
class pulse:
"""
An ADT class to hold pulse information.
"""
def __init__(self, gpio_on, gpio_off, delay):
"""
Initialises a pulse ADT.
gpio_on: the gpios to switch on at the start of the pulse.
gpio_off: the gpios to switch off at the start of the pulse.
delay: the delay in microseconds before the next pulse.
"""
self.gpio_on = gpio_on
self.gpio_off = gpio_off
self.delay = delay
def wave_clear():
"""
Initialises a new waveform.
Returns 0 if OK.
A waveform comprises one of more pulses.
A pulse specifies
1) the gpios to be switched on at the start of the pulse.
2) the gpios to be switched off at the start of the pulse.
3) the delay in microseconds before the next pulse.
Any or all the fields can be zero. It doesn't make any sense
to set all the fields to zero (the pulse will be ignored).
When a waveform is started each pulse is executed in order with
the specified delay between the pulse and the next.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVCLR, 0, 0))
def wave_add_generic(pulses):
"""
Adds a list of pulses to the current waveform.
Returns the new total number of pulses in the current waveform
if OK, otherwise PI_TOO_MANY_PULSES.
pulses: list of pulses to add to the waveform.
The pulses are interleaved in time order within the existing
waveform (if any).
Merging allows the waveform to be built in parts, that is the
settings for gpio#1 can be added, and then gpio#2 etc.
If the added waveform is intended to start after or within
the existing waveform then the first pulse should consist
solely of a delay.
Example
#!/usr/bin/env python
import time
import pigpio
class stepper:
def __init__(self, g1, g2, g3, g4):
self.g1 = g1
self.g2 = g2
self.g3 = g3
self.g4 = g4
self.all = (1<<g1 | 1<<g2 | 1<<g3 | 1<<g4)
pigpio.set_mode(g1, pigpio.OUTPUT)
pigpio.set_mode(g2, pigpio.OUTPUT)
pigpio.set_mode(g3, pigpio.OUTPUT)
pigpio.set_mode(g4, pigpio.OUTPUT)
def step_on(self, pos):
if pos == 0: return (1<<self.g4)
elif pos == 1: return (1<<self.g3 | 1<<self.g4)
elif pos == 2: return (1<<self.g3)
elif pos == 3: return (1<<self.g2 | 1<<self.g3)
elif pos == 4: return (1<<self.g2)
elif pos == 5: return (1<<self.g1 | 1<<self.g2)
elif pos == 6: return (1<<self.g1)
elif pos == 7: return (1<<self.g1 | 1<<self.g4)
else: return 0
def step_off(self, pos):
return self.step_on(pos) ^ self.all
pigpio.start()
s1 = stepper(14, 15, 18, 17)
s2 = stepper(24, 25, 8, 7)
f1=[] # pulses to drive stepper 1 forward
b2=[] # pulses to drive stepper 2 backward
for i in range(8):
f1.append(pigpio.pulse(s1.step_on(i), s1.step_off(i), 1200))
b2.append(pigpio.pulse(s2.step_on(7-i), s2.step_off(7-i), 1200))
pigpio.wave_clear() # initialise a new waveform
pigpio.wave_add_generic(f1) # add stepper 1 forward
pigpio.wave_add_generic(b2) # add stepper 2 backward
pigpio.wave_tx_repeat() # repeately transmit pulses
time.sleep(10)
pigpio.wave_tx_stop() # stop waveform
pigpio.stop()
"""
# pigpio message format
# I p1 number of pulses
# I p2 0
## extension ##
# III on/off/delay * number of pulses
msg = ""
for p in pulses:
msg += struct.pack("III", p.gpio_on, p.gpio_off, p.delay)
extents = [msg]
return _u2i(_pigpio_command_ext(
_control, _PI_CMD_WVAG, len(pulses), 0, extents))
def wave_add_serial(user_gpio, baud, offset, data):
"""
Adds a waveform representing serial data to the existing waveform
(if any). The serial data starts offset microseconds from the
start of the waveform.
Returns the new total number of pulses in the current waveform
if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD,
PI_TOO_MANY_CHARS, PI_BAD_SER_OFFSET, or PI_TOO_MANY_PULSES.
user_gpio: gpio to transmit data. You must set the gpio mode
to output.
baud: baud rate to use.
offset: number of microseconds from the starts of the waveform.
data: the data to transmit.
The serial data is formatted as one start bit, eight data bits,
and one stop bit.
It is legal to add serial data streams with different baud rates
to the same waveform.
Example
#!/usr/bin/env python
import time
import pigpio
GPIO=24
pigpio.start()
pigpio.set_mode(TX_GPIO, pigpio.OUTPUT)
pigpio.wave_clear() # initialise waveform
for i in range(10):
pigpio.wave_add_serial(
GPIO, 9600, i*2000000, "{} seconds in.\r\n".format(i*2))
pigpio.wave_tx_start()
time.sleep(22)
pigpio.stop()
"""
# pigpio message format
# I p1 user_gpio
# I p2 len(data)
## extension ##
# I baud
# I offset
# s data
extents = [struct.pack("I", baud),struct.pack("I", offset), data]
return _u2i(_pigpio_command_ext(
_control, _PI_CMD_WVAS, user_gpio, len(data), extents))
def wave_tx_busy():
"""
Checks to see if a waveform is currently being transmitted.
Returns 1 if a waveform is currently being transmitted, otherwise 0.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVBSY, 0, 0))
def wave_tx_stop():
"""
Stops the transmission of the current waveform.
Returns 0 if OK.
This function is intended to stop a waveform started with
wave_tx_repeat().
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVHLT, 0, 0))
def wave_tx_start():
"""
Transmits the current waveform. The waveform is sent once.
Returns the number of cbs in the waveform if OK,
otherwise PI_BAD_WAVE_MODE.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVGO, 0, 0))
def wave_tx_repeat():
"""
Transmits the current waveform. The waveform repeats until
wave_tx_stop is called.
Returns the number of cbs in the waveform if OK,
otherwise PI_BAD_WAVE_MODE.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVGOR, 0, 0))
def wave_get_micros():
"""
Returns the length in microseconds of the current waveform.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVSM, 0, 0))
def wave_get_max_micros():
"""
Returns the maximum possible size of a waveform in microseconds.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVSM, 2, 0))
def wave_get_pulses():
"""
Returns the length in pulses of the current waveform.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVSP, 0, 0))
def wave_get_max_pulses():
"""
Returns the maximum possible size of a waveform in pulses.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVSP, 2, 0))
def wave_get_cbs():
"""
Returns the length in DMA control blocks of the current waveform.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVSC, 0, 0))
def wave_get_max_cbs():
"""
Returns the maximum possible size of a waveform in DMA control blocks.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVSC, 2, 0))
def gpio_trigger(user_gpio, pulse_len=10, level=1):
"""
Send a trigger pulse to a gpio. The gpio is set to
level for pulse_len microseconds and then reset to not level.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_LEVEL,
PI_BAD_PULSELEN, or PI_NOT_PERMITTED.
user_gpio: gpio to pulse.
pulse_len: length of pulse in microseconds.
level: whether the pulse should be high or low.
Example
#!/usr/bin/env python
import time
import pigpio
GPIO=24
pigpio.start()
for i in range(10):
pigpio.gpio_trigger(GPIO, (i*5)+10, 1)
time.sleep(1)
pigpio.stop()
"""
# pigpio message format
# I p1 user_gpio
# I p2 pulse_len
## extension ##
# I level
extents = [struct.pack("I", level)]
return _u2i(_pigpio_command_ext(
_control, _PI_CMD_TRIG, user_gpio, pulse_len, extents))
def store_script(script):
"""
Store a script for later execution.
Returns a script id if OK, otherwise PI_BAD_SCRIPT.
"""
# I p1 script length
# I p2 0
## extension ##
# s script
return _u2i(_pigpio_command_ext(
_control, _PI_CMD_PROC, len(script), 0, script))
def run_script(script_id):
"""
Runs a stored script.
Returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
script_id: script_id of stored script.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_PROCR, script_id, 0))
def stop_script(script_id):
"""
Stops a running script.
Returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
script_id: script_id of stored script.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_PROCS, script_id, 0))
def delete_script(script_id):
"""
Deletes a stored script.
Returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
script_id: script_id of stored script.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_PROCD, script_id, 0))
class callback: class callback:
"""A class to provide gpio level change callbacks.""" """A class to provide gpio level change callbacks."""
@ -1332,8 +1726,8 @@ class callback:
import time import time
def cbf(g, L, t): def cbf(g, L, t):
message = "gpio=" + str(g) + " level=" + str(L) + " at " + str(t) s = "gpio=" + str(g) + " level=" + str(L) + " at " + str(t)
print(message) print(s)
pigpio.start() pigpio.start()
@ -1376,9 +1770,9 @@ class callback:
tally_2 = cb.tally() tally_2 = cb.tally()
message = "counted " + str(tally_2 - tally_1) + " edges" s = "counted " + str(tally_2 - tally_1) + " edges"
print(message) print(s)
cb.cancel() cb.cancel()
@ -1411,9 +1805,9 @@ class callback:
tally_2 = cb.tally() tally_2 = cb.tally()
message = "counted " + str(tally_2 - tally_1) + " rising edges" s = "counted " + str(tally_2 - tally_1) + " rising edges"
print(message) print(s)
cb.cancel() cb.cancel()

View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 7+ This version is for pigpio version 11+
*/ */
#include <sys/types.h> #include <sys/types.h>
@ -34,6 +34,7 @@ This version is for pigpio version 7+
#include <pwd.h> #include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
@ -43,7 +44,6 @@ This version is for pigpio version 7+
#include <ctype.h> #include <ctype.h>
#include "pigpio.h" #include "pigpio.h"
#include "command.h"
/* /*
This program starts the pigpio library as a daemon. This program starts the pigpio library as a daemon.
@ -61,6 +61,22 @@ static uint64_t updateMask = -1;
static FILE * errFifo; static FILE * errFifo;
void fatal(char *fmt, ...)
{
char buf[128];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
fprintf(stderr, "%s\n", buf);
fflush(stderr);
exit(EXIT_FAILURE);
}
void usage() void usage()
{ {
fprintf(stderr, "\n" \ fprintf(stderr, "\n" \
@ -98,21 +114,21 @@ static void initOpts(int argc, char *argv[])
i = atoi(optarg); i = atoi(optarg);
if ((i >= PI_BUF_MILLIS_MIN) && (i <= PI_BUF_MILLIS_MAX)) if ((i >= PI_BUF_MILLIS_MIN) && (i <= PI_BUF_MILLIS_MAX))
bufferSizeMilliseconds = i; bufferSizeMilliseconds = i;
else cmdFatal("invalid -b option (%d)", i); else fatal("invalid -b option (%d)", i);
break; break;
case 'd': case 'd':
i = atoi(optarg); i = atoi(optarg);
if ((i >= PI_MIN_DMA_CHANNEL) && (i <= PI_MAX_PRIMARY_CHANNEL)) if ((i >= PI_MIN_DMA_CHANNEL) && (i <= PI_MAX_PRIMARY_CHANNEL))
DMAprimaryChannel = i; DMAprimaryChannel = i;
else cmdFatal("invalid -d option (%d)", i); else fatal("invalid -d option (%d)", i);
break; break;
case 'e': case 'e':
i = atoi(optarg); i = atoi(optarg);
if ((i >= PI_MIN_DMA_CHANNEL) && (i <= PI_MAX_SECONDARY_CHANNEL)) if ((i >= PI_MIN_DMA_CHANNEL) && (i <= PI_MAX_SECONDARY_CHANNEL))
DMAsecondaryChannel = i; DMAsecondaryChannel = i;
else cmdFatal("invalid -e option (%d)", i); else fatal("invalid -e option (%d)", i);
break; break;
case 'f': case 'f':
@ -127,7 +143,7 @@ static void initOpts(int argc, char *argv[])
i = atoi(optarg); i = atoi(optarg);
if ((i >= PI_MIN_SOCKET_PORT) && (i <= PI_MAX_SOCKET_PORT)) if ((i >= PI_MIN_SOCKET_PORT) && (i <= PI_MAX_SOCKET_PORT))
socketPort = i; socketPort = i;
else cmdFatal("invalid -p option (%d)", i); else fatal("invalid -p option (%d)", i);
break; break;
case 's': case 's':
@ -145,7 +161,7 @@ static void initOpts(int argc, char *argv[])
break; break;
default: default:
cmdFatal("invalid -s option (%d)", i); fatal("invalid -s option (%d)", i);
break; break;
} }
break; break;
@ -154,21 +170,21 @@ static void initOpts(int argc, char *argv[])
i = atoi(optarg); i = atoi(optarg);
if ((i >= PI_CLOCK_PWM) && (i <= PI_CLOCK_PCM)) if ((i >= PI_CLOCK_PWM) && (i <= PI_CLOCK_PCM))
clockPeripheral = i; clockPeripheral = i;
else cmdFatal("invalid -t option (%d)", i); else fatal("invalid -t option (%d)", i);
break; break;
case 'u': case 'u':
i = atoi(optarg); i = atoi(optarg);
if ((i >= PI_CLOCK_OSC) && (i <= PI_CLOCK_PLLD)) if ((i >= PI_CLOCK_OSC) && (i <= PI_CLOCK_PLLD))
clockSource = i; clockSource = i;
else cmdFatal("invalid -u option (%d)", i); else fatal("invalid -u option (%d)", i);
break; break;
case 'x': case 'x':
mask = strtoll(optarg, &endptr, 0); mask = strtoll(optarg, &endptr, 0);
printf("mask=%llx\n", mask); printf("mask=%llx\n", mask);
if (!*endptr) updateMask = mask; if (!*endptr) updateMask = mask;
else cmdFatal("invalid -x option (%s)", optarg); else fatal("invalid -x option (%s)", optarg);
break; break;
default: /* '?' */ default: /* '?' */
@ -221,11 +237,11 @@ int main(int argc, char **argv)
/* Create a new SID for the child process */ /* Create a new SID for the child process */
if (setsid() < 0) cmdFatal("setsid failed (%m)"); if (setsid() < 0) fatal("setsid failed (%m)");
/* Change the current working directory */ /* Change the current working directory */
if ((chdir("/")) < 0) cmdFatal("chdir failed (%m)"); if ((chdir("/")) < 0) fatal("chdir failed (%m)");
/* check command line parameters */ /* check command line parameters */
@ -252,7 +268,7 @@ int main(int argc, char **argv)
/* start library */ /* start library */
if (gpioInitialise()< 0) cmdFatal("Can't initialise pigpio library"); if (gpioInitialise()< 0) fatal("Can't initialise pigpio library");
/* create pipe for error reporting */ /* create pipe for error reporting */
@ -261,7 +277,7 @@ int main(int argc, char **argv)
mkfifo(PI_ERRFIFO, 0664); mkfifo(PI_ERRFIFO, 0664);
if (chmod(PI_ERRFIFO, 0664) < 0) if (chmod(PI_ERRFIFO, 0664) < 0)
cmdFatal("chmod %s failed (%m)", PI_ERRFIFO); fatal("chmod %s failed (%m)", PI_ERRFIFO);
errFifo = freopen(PI_ERRFIFO, "w+", stderr); errFifo = freopen(PI_ERRFIFO, "w+", stderr);

View File

@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/> For more information, please refer to <http://unlicense.org/>
*/ */
/* PIGPIOD_IF_VERSION 1 */ /* PIGPIOD_IF_VERSION 2 */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -97,10 +97,34 @@ static int pigpio_command(int fd, int command, int p1, int p2)
cmd.p2 = p2; cmd.p2 = p2;
cmd.res = 0; cmd.res = 0;
if (send(fd, &cmd, sizeof(cmdCmd_t), 0) != sizeof(cmdCmd_t)) if (send(fd, &cmd, sizeof(cmd), 0) != sizeof(cmd)) return pigif_bad_send;
return pigif_bad_send;
if (recv(fd, &cmd, sizeof(cmdCmd_t), MSG_WAITALL) != sizeof(cmdCmd_t)) if (recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd))
return pigif_bad_recv;
return cmd.res;
}
static int pigpio_command_ext
(int fd, int command, int p1, int p2, int extents, gpioExtent_t *ext)
{
int i;
cmdCmd_t cmd;
cmd.cmd = command;
cmd.p1 = p1;
cmd.p2 = p2;
cmd.res = 0;
if (send(fd, &cmd, sizeof(cmd), 0) != sizeof(cmd)) return pigif_bad_send;
for (i=0; i<extents; i++)
{
if (send(fd, ext[i].ptr, ext[i].n, 0) != ext[i].n)
return pigif_bad_send;
}
if (recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd))
return pigif_bad_recv; return pigif_bad_recv;
return cmd.res; return cmd.res;
@ -390,7 +414,7 @@ unsigned pigpiod_if_version(void)
return PIGPIOD_IF_VERSION; return PIGPIOD_IF_VERSION;
} }
pthread_t *start_thread(ThreadFunc_t func, void *arg) pthread_t *start_thread(gpioThreadFunc_t func, void *arg)
{ {
pthread_t *pth; pthread_t *pth;
pthread_attr_t pthAttr; pthread_attr_t pthAttr;
@ -501,144 +525,219 @@ void pigpio_stop(void)
} }
int set_mode(int gpio, int mode) int set_mode(int gpio, int mode)
{ {return pigpio_command(gPigCommand, PI_CMD_MODES, gpio, mode);}
return pigpio_command(gPigCommand, PI_CMD_MODES, gpio, mode);
}
int get_mode(int gpio) int get_mode(int gpio)
{ {return pigpio_command(gPigCommand, PI_CMD_MODEG, gpio, 0);}
return pigpio_command(gPigCommand, PI_CMD_MODEG, gpio, 0);
}
int set_pull_up_down(int gpio, int pud) int set_pull_up_down(int gpio, int pud)
{ {return pigpio_command(gPigCommand, PI_CMD_PUD, gpio, pud);}
return pigpio_command(gPigCommand, PI_CMD_PUD, gpio, pud);
}
int read_gpio(int gpio) int read_gpio(int gpio)
{ {return pigpio_command(gPigCommand, PI_CMD_READ, gpio, 0);}
return pigpio_command(gPigCommand, PI_CMD_READ, gpio, 0);
}
int write_gpio(int gpio, int level) int write_gpio(int gpio, int level)
{ {return pigpio_command(gPigCommand, PI_CMD_WRITE, gpio, level);}
return pigpio_command(gPigCommand, PI_CMD_WRITE, gpio, level);
}
int set_PWM_dutycycle(int user_gpio, int dutycycle) int set_PWM_dutycycle(int user_gpio, int dutycycle)
{ {return pigpio_command(gPigCommand, PI_CMD_PWM, user_gpio, dutycycle);}
return pigpio_command(gPigCommand, PI_CMD_PWM, user_gpio, dutycycle);
}
int set_PWM_range(int user_gpio, int range_) int set_PWM_range(int user_gpio, int range_)
{ {return pigpio_command(gPigCommand, PI_CMD_PRS, user_gpio, range_);}
return pigpio_command(gPigCommand, PI_CMD_PRS, user_gpio, range_);
}
int get_PWM_range(int user_gpio) int get_PWM_range(int user_gpio)
{ {return pigpio_command(gPigCommand, PI_CMD_PRG, user_gpio, 0);}
return pigpio_command(gPigCommand, PI_CMD_PRG, user_gpio, 0);
}
int get_PWM_real_range(int user_gpio) int get_PWM_real_range(int user_gpio)
{ {return pigpio_command(gPigCommand, PI_CMD_PRRG, user_gpio, 0);}
return pigpio_command(gPigCommand, PI_CMD_PRRG, user_gpio, 0);
}
int set_PWM_frequency(int user_gpio, int frequency) int set_PWM_frequency(int user_gpio, int frequency)
{ {return pigpio_command(gPigCommand, PI_CMD_PFS, user_gpio, frequency);}
return pigpio_command(gPigCommand, PI_CMD_PFS, user_gpio, frequency);
}
int get_PWM_frequency(int user_gpio) int get_PWM_frequency(int user_gpio)
{ {return pigpio_command(gPigCommand, PI_CMD_PFG, user_gpio, 0);}
return pigpio_command(gPigCommand, PI_CMD_PFG, user_gpio, 0);
}
int set_servo_pulsewidth(int user_gpio, int pulsewidth) int set_servo_pulsewidth(int user_gpio, int pulsewidth)
{ {return pigpio_command(gPigCommand, PI_CMD_SERVO, user_gpio, pulsewidth);}
return pigpio_command(gPigCommand, PI_CMD_SERVO, user_gpio, pulsewidth);
}
int notify_open(void) int notify_open(void)
{ {return pigpio_command(gPigCommand, PI_CMD_NO, 0, 0);}
return pigpio_command(gPigCommand, PI_CMD_NO, 0, 0);
}
int notify_begin(int handle, uint32_t bits) int notify_begin(int handle, uint32_t bits)
{ {return pigpio_command(gPigCommand, PI_CMD_NB, handle, bits);}
return pigpio_command(gPigCommand, PI_CMD_NB, handle, bits);
}
int notify_pause(int handle) int notify_pause(int handle)
{ {return pigpio_command(gPigCommand, PI_CMD_NB, handle, 0);}
return pigpio_command(gPigCommand, PI_CMD_NB, handle, 0);
}
int notify_close(int handle) int notify_close(int handle)
{ {return pigpio_command(gPigCommand, PI_CMD_NC, handle, 0);}
return pigpio_command(gPigCommand, PI_CMD_NC, handle, 0);
}
int set_watchdog(int user_gpio, int timeout) int set_watchdog(int user_gpio, int timeout)
{ {return pigpio_command(gPigCommand, PI_CMD_WDOG, user_gpio, timeout);}
return pigpio_command(gPigCommand, PI_CMD_WDOG, user_gpio, timeout);
}
uint32_t read_bank_1(void) uint32_t read_bank_1(void)
{ {return pigpio_command(gPigCommand, PI_CMD_BR1, 0, 0);}
return pigpio_command(gPigCommand, PI_CMD_BR1, 0, 0);
}
uint32_t read_bank_2(void) uint32_t read_bank_2(void)
{ {return pigpio_command(gPigCommand, PI_CMD_BR2, 0, 0);}
return pigpio_command(gPigCommand, PI_CMD_BR2, 0, 0);
}
int clear_bank_1(uint32_t levels) int clear_bank_1(uint32_t levels)
{ {return pigpio_command(gPigCommand, PI_CMD_BC1, levels, 0);}
return pigpio_command(gPigCommand, PI_CMD_BC1, levels, 0);
}
int clear_bank_2(uint32_t levels) int clear_bank_2(uint32_t levels)
{ {return pigpio_command(gPigCommand, PI_CMD_BC2, levels, 0);}
return pigpio_command(gPigCommand, PI_CMD_BC2, levels, 0);
}
int set_bank_1(uint32_t levels) int set_bank_1(uint32_t levels)
{ {return pigpio_command(gPigCommand, PI_CMD_BS1, levels, 0);}
return pigpio_command(gPigCommand, PI_CMD_BS1, levels, 0);
}
int set_bank_2(uint32_t levels) int set_bank_2(uint32_t levels)
{ {return pigpio_command(gPigCommand, PI_CMD_BS2, levels, 0);}
return pigpio_command(gPigCommand, PI_CMD_BS2, levels, 0);
}
uint32_t get_current_tick(void) uint32_t get_current_tick(void)
{ {return pigpio_command(gPigCommand, PI_CMD_TICK, 0, 0);}
return pigpio_command(gPigCommand, PI_CMD_TICK, 0, 0);
}
uint32_t get_hardware_revision(void) uint32_t get_hardware_revision(void)
{ {return pigpio_command(gPigCommand, PI_CMD_HWVER, 0, 0);}
return pigpio_command(gPigCommand, PI_CMD_HWVER, 0, 0);
}
unsigned get_pigpio_version(void) unsigned get_pigpio_version(void)
{return pigpio_command(gPigCommand, PI_CMD_PIGPV, 0, 0);}
int wave_clear(void)
{return pigpio_command(gPigCommand, PI_CMD_WVCLR, 0, 0);}
int wave_add_generic(unsigned numPulses, gpioPulse_t *pulses)
{ {
return pigpio_command(gPigCommand, PI_CMD_PIGPV, 0, 0); gpioExtent_t ext[1];
/*
p1=numPulses
p2=0
## extension ##
gpioPulse_t[] pulses
*/
ext[0].n = numPulses * sizeof(gpioPulse_t);
ext[0].ptr = pulses;
return pigpio_command_ext(gPigCommand, PI_CMD_WVAG, numPulses, 0, 1, ext);
} }
int wave_add_serial(
unsigned gpio, unsigned baud, unsigned offset, unsigned numChar, char *str)
{
gpioExtent_t ext[3];
/*
p1=gpio
p2=numChar
## extension ##
unsigned baud
unsigned offset
char[] str
*/
ext[0].n = sizeof(unsigned);
ext[0].ptr = &baud;
ext[1].n = sizeof(unsigned);
ext[1].ptr = &offset;
ext[2].n = numChar;
ext[2].ptr = str;
return pigpio_command_ext(gPigCommand, PI_CMD_WVAS, gpio, numChar, 3, ext);
}
int wave_tx_busy(void)
{return pigpio_command(gPigCommand, PI_CMD_WVBSY, 0, 0);}
int wave_tx_stop(void)
{return pigpio_command(gPigCommand, PI_CMD_WVHLT, 0, 0);}
int wave_tx_start(void)
{return pigpio_command(gPigCommand, PI_CMD_WVGO, 0, 0);}
int wave_tx_repeat(void)
{return pigpio_command(gPigCommand, PI_CMD_WVGOR, 0, 0);}
int wave_get_micros(void)
{return pigpio_command(gPigCommand, PI_CMD_WVSM, 0, 0);}
int wave_get_high_micros(void)
{return pigpio_command(gPigCommand, PI_CMD_WVSM, 1, 0);}
int wave_get_max_micros(void)
{return pigpio_command(gPigCommand, PI_CMD_WVSM, 2, 0);}
int wave_get_pulses(void)
{return pigpio_command(gPigCommand, PI_CMD_WVSP, 0, 0);}
int wave_get_high_pulses(void)
{return pigpio_command(gPigCommand, PI_CMD_WVSP, 1, 0);}
int wave_get_max_pulses(void)
{return pigpio_command(gPigCommand, PI_CMD_WVSP, 2, 0);}
int wave_get_cbs(void)
{return pigpio_command(gPigCommand, PI_CMD_WVSC, 0, 0);}
int wave_get_high_cbs(void)
{return pigpio_command(gPigCommand, PI_CMD_WVSC, 1, 0);}
int wave_get_max_cbs(void)
{return pigpio_command(gPigCommand, PI_CMD_WVSC, 2, 0);}
int gpio_trigger(unsigned gpio, unsigned pulseLen, unsigned level)
{
gpioExtent_t ext[1];
/*
p1=gpio
p2=pulseLen
## extension ##
unsigned level
*/
ext[0].n = sizeof(level);
ext[0].ptr = &level;
return pigpio_command_ext(gPigCommand, PI_CMD_TRIG, gpio, pulseLen, 1, ext);
}
int store_script(char *script)
{
unsigned len;
gpioExtent_t ext[1];
/*
p1=script length
p2=0
## extension ##
char[] script
*/
len = strlen(script);
ext[0].n = len;
ext[0].ptr = script;
return pigpio_command_ext(gPigCommand, PI_CMD_PROC, len, 0, 1, ext);
}
int run_script(int script_id)
{return pigpio_command(gPigCommand, PI_CMD_PROCR, script_id, 0);}
int stop_script(int script_id)
{return pigpio_command(gPigCommand, PI_CMD_PROCS, script_id, 0);}
int delete_script(int script_id)
{return pigpio_command(gPigCommand, PI_CMD_PROCD, script_id, 0);}
int callback(int gpio, int edge, CBFunc_t f) int callback(int gpio, int edge, CBFunc_t f)
{ {return intCallback(gpio, edge, f, 0, 0);}
return intCallback(gpio, edge, f, 0, 0);
}
int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user) int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user)
{ {return intCallback(gpio, edge, f, user, 1);}
return intCallback(gpio, edge, f, user, 1);
}
int callback_cancel(int id) int callback_cancel(int id)
{ {

View File

@ -30,7 +30,7 @@ For more information, please refer to <http://unlicense.org/>
#include "pigpio.h" #include "pigpio.h"
#define PIGPIOD_IF_VERSION 1 #define PIGPIOD_IF_VERSION 2
typedef enum typedef enum
{ {
@ -70,7 +70,7 @@ const char *pigpio_error(int error);
unsigned pigpiod_if_version(void); unsigned pigpiod_if_version(void);
/* Return the pigpiod_if version. */ /* Return the pigpiod_if version. */
pthread_t *start_thread(ThreadFunc_t func, void *arg); pthread_t *start_thread(gpioThreadFunc_t func, void *arg);
/* Starts a new thread of execution with func as the main routine. /* Starts a new thread of execution with func as the main routine.
Returns a pointer to pthread_t if OK, otherwise NULL. Returns a pointer to pthread_t if OK, otherwise NULL.
@ -198,7 +198,6 @@ int set_PWM_range(int user_gpio, int range_);
The real value set by set_PWM_range is The real value set by set_PWM_range is
(dutycycle * real range) / range. (dutycycle * real range) / range.
*/ */
int get_PWM_range(int user_gpio); int get_PWM_range(int user_gpio);
@ -507,20 +506,213 @@ uint32_t get_hardware_revision(void);
hexadecimal number the function returns 0. hexadecimal number the function returns 0.
*/ */
int wave_clear(void);
/* This function initialises a new waveform.
Returns 0 if OK.
A waveform comprises one of more pulses. Each pulse consists of a
gpioPulse_t structure.
typedef struct
{
uint32_t gpioOn;
uint32_t gpioOff;
uint32_t usDelay;
} gpioPulse_t;
The fields specify
1) the gpios to be switched on at the start of the pulse.
2) the gpios to be switched off at the start of the pulse.
3) the delay in microseconds before the next pulse.
Any or all the fields can be zero. It doesn't make any sense to
set all the fields to zero (the pulse will be ignored).
When a waveform is started each pulse is executed in order with the
specified delay between the pulse and the next.
*/
int wave_tx_busy(void);
/* This function checks to see if a waveform is currently being
transmitted.
Returns 1 if a waveform is currently being transmitted, otherwise 0.
*/
int wave_tx_stop(void);
/* This function stops the transmission of the current waveform.
Returns 0 if OK.
This function is intended to stop a waveform started with the repeat mode.
*/
int wave_tx_start(void);
/* This function transmits the current waveform. The waveform is
sent once.
Returns the number of DMA control blocks in the waveform if OK,
otherwise PI_BAD_WAVE_MODE.
*/
int wave_tx_repeat(void);
/* This function transmits the current waveform. The waveform repeats
endlessly until wave_tx_stop is called.
Returns the number of DMA control blocks in the waveform if OK,
otherwise PI_BAD_WAVE_MODE.
*/
int wave_add_generic(unsigned numPulses, gpioPulse_t *pulses);
/* This function adds a number of pulses to the current waveform.
Returns the new total number of pulses in the current waveform if OK,
otherwise PI_TOO_MANY_PULSES.
The pulses are interleaved in time order within the existing waveform
(if any).
Merging allows the waveform to be built in parts, that is the settings
for gpio#1 can be added, and then gpio#2 etc.
If the added waveform is intended to start after or within the existing
waveform then the first pulse should consist solely of a delay.
*/
int wave_add_serial
(unsigned gpio, unsigned baud, unsigned offset, unsigned numChar, char *str);
/* This function adds a waveform representing serial data to the
existing waveform (if any). The serial data starts offset microseconds
from the start of the waveform.
Returns the new total number of pulses in the current waveform if OK,
otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_TOO_MANY_CHARS, or
PI_TOO_MANY_PULSES.
NOTES:
The serial data is formatted as one start bit, eight data bits, and one
stop bit.
It is legal to add serial data streams with different baud rates to
the same waveform.
*/
int wave_get_micros(void);
/* This function returns the length in microseconds of the current
waveform.
*/
int wave_get_high_micros(void);
/* This function returns the length in microseconds of the longest waveform
created since the pigpio daemon was started..
*/
int wave_get_max_micros(void);
/* This function returns the maximum possible size of a waveform in
microseconds.
*/
int wave_get_pulses(void);
/* This function returns the length in pulses of the current waveform.
*/
int wave_get_high_pulses(void);
/* This function returns the length in pulses of the longest waveform
created since the pigpio daemon was started..
*/
int wave_get_max_pulses(void);
/* This function returns the maximum possible size of a waveform in pulses.
*/
int wave_get_cbs(void);
/* This function returns the length in DMA control blocks of the current
waveform.
*/
int wave_get_high_cbs(void);
/* This function returns the length in DMA control blocks of the longest
waveform created since the pigpio daemon was started..
*/
int wave_get_max_cbs(void);
/* This function returns the maximum possible size of a waveform in DMA
control blocks.
*/
int gpio_trigger(unsigned gpio, unsigned pulseLen, unsigned level);
/* This function sends a trigger pulse to a gpio. The gpio is set to
level for pulseLen microseconds and then reset to not level.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_LEVEL,
PI_BAD_PULSELEN, or PI_NOT_PERMITTED.
*/
int store_script(char *script);
/* This function stores a script for later execution.
The function returns a script id if the script is valid,
otherwise PI_BAD_SCRIPT.
*/
int run_script(int script_id);
/* This function runs a stored script.
The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
*/
int stop_script(int script_id);
/* This function stops a running script.
The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
*/
int delete_script(int script_id);
/* This function deletes a stored script.
The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
*/
int callback(int gpio, int edge, CBFunc_t f); int callback(int gpio, int edge, CBFunc_t f);
/* /*
This function initialises a new callback.
The function returns a callback id if OK, otherwise pigif_bad_malloc,
pigif_duplicate_callback, or pigif_bad_callback.
The callback is called with the gpio, edge, and tick, whenever the
gpio has the identified edge.
*/ */
int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user); int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user);
/* /*
This function initialises a new callback.
The function returns a callback id if OK, otherwise pigif_bad_malloc,
pigif_duplicate_callback, or pigif_bad_callback.
The callback is called with the gpio, edge, tick, and user, whenever
the gpio has the identified edge.
*/ */
int callback_cancel(int id); int callback_cancel(int id);
/* /*
This function cancels a callback identified by its id.
The function returns 0 if OK, otherwise pigif_callback_not_found.
*/ */
int wait_for_edge(int gpio, int edge, double timeout); int wait_for_edge(int gpio, int edge, double timeout);
/* /*
This function waits for edge on the gpio for up to timeout
seconds.
The function returns 1 if the edge occurred, otherwise 0.
The function returns when the edge occurs or after the timeout.
*/ */
#endif #endif

63
pigs.c
View File

@ -26,11 +26,12 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 7+ This version is for pigpio version 11+
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -42,10 +43,26 @@ This version is for pigpio version 7+
#include "command.h" #include "command.h"
/* /*
This program provides a socket interface This program provides a socket interface to some of
to the commands available from pigpio. the commands available from pigpio.
*/ */
void fatal(char *fmt, ...)
{
char buf[128];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
fprintf(stderr, "%s\n", buf);
fflush(stderr);
exit(EXIT_FAILURE);
}
static int openSocket(void) static int openSocket(void)
{ {
int sock, err; int sock, err;
@ -88,9 +105,10 @@ static int openSocket(void)
int main(int argc , char *argv[]) int main(int argc , char *argv[])
{ {
int sock, r, idx; int sock, r, idx, i;
cmdCmd_t cmd; cmdCmd_t cmd;
char buf[128]; gpioExtent_t ext[3];
char buf[1024];
sock = openSocket(); sock = openSocket();
@ -113,31 +131,48 @@ int main(int argc , char *argv[])
sprintf(buf, "%10s %10s %10s", argv[1], argv[2], argv[3]); sprintf(buf, "%10s %10s %10s", argv[1], argv[2], argv[3]);
break; break;
case 5:
sprintf(buf, "%10s %10s %10s %10s",
argv[1], argv[2], argv[3], argv[4]);
break;
case 6:
sprintf(buf, "%10s %10s %10s %10s %10s",
argv[1], argv[2], argv[3], argv[4], argv[5]);
break;
default: default:
cmdFatal("what?"); fatal("what? 'pigs h' for help");
} }
if ((idx=cmdParse(buf, &cmd)) >= 0) if ((idx=cmdParse(buf, &cmd, argc, argv, ext)) >= 0)
{ {
if (send(sock, &cmd, sizeof(cmdCmd_t), 0) == sizeof(cmdCmd_t)) if (send(sock, &cmd, sizeof(cmdCmd_t), 0) == sizeof(cmdCmd_t))
{ {
/* send extensions */
for (i=0; i<cmdInfo[idx].ext; i++)
{
send(sock, ext[i].ptr, ext[i].n, 0);
}
if (recv(sock, &cmd, sizeof(cmdCmd_t), 0) == sizeof(cmdCmd_t)) if (recv(sock, &cmd, sizeof(cmdCmd_t), 0) == sizeof(cmdCmd_t))
{ {
switch (cmdInfo[idx].rv) switch (cmdInfo[idx].rv)
{ {
case 0: case 0:
r = cmd.res; r = cmd.res;
if (r < 0) cmdFatal("ERROR: %s", cmdErrStr(r)); if (r < 0) fatal("ERROR: %s", cmdErrStr(r));
break; break;
case 1: case 1:
r = cmd.res; r = cmd.res;
if (r < 0) cmdFatal("ERROR: %s", cmdErrStr(r)); if (r < 0) fatal("ERROR: %s", cmdErrStr(r));
break; break;
case 2: case 2:
r = cmd.res; r = cmd.res;
if (r < 0) cmdFatal("ERROR: %s", cmdErrStr(r)); if (r < 0) fatal("ERROR: %s", cmdErrStr(r));
else printf("%d\n", r); else printf("%d\n", r);
break; break;
@ -154,13 +189,13 @@ int main(int argc , char *argv[])
break; break;
} }
} }
else cmdFatal("recv failed, %m"); else fatal("recv failed, %m");
} }
else cmdFatal("send failed, %m"); else fatal("send failed, %m");
} }
else cmdFatal("what?"); else fatal("what? 'pigs h' for help");
} }
else cmdFatal("connect failed, %m"); else fatal("connect failed, %m");
close(sock); close(sock);

View File

@ -3,7 +3,7 @@
from distutils.core import setup from distutils.core import setup
setup(name='pigpio', setup(name='pigpio',
version='1.1', version='1.2',
author='joan', author='joan',
author_email='joan@abyz.me.uk', author_email='joan@abyz.me.uk',
maintainer='joan', maintainer='joan',
@ -11,7 +11,7 @@ setup(name='pigpio',
url='http://abyz.co.uk/rpi/pigpio/python.html/', url='http://abyz.co.uk/rpi/pigpio/python.html/',
description='Raspberry Pi gpio module', description='Raspberry Pi gpio module',
long_description='Raspberry Pi Python module for access to the pigpio daemon', long_description='Raspberry Pi Python module for access to the pigpio daemon',
download_url='http://abyz.co.uk/rpi/pigpio/pigpio.tar', download_url='http://abyz.co.uk/rpi/pigpio/pigpio.zip',
license='TBD', license='TBD',
py_modules=['pigpio'] py_modules=['pigpio']
) )