This commit is contained in:
joan 2013-12-12 10:32:49 +00:00
parent 56b5f62885
commit 3e7e75ea29
10 changed files with 2002 additions and 202 deletions

View File

@ -5,7 +5,9 @@ SIZE = size
CFLAGS = -O3 -Wall CFLAGS = -O3 -Wall
all: libpigpio.a checklib demolib pig2vcd pigpiod pigs ALL = libpigpio.a checklib demolib pig2vcd pigpiod pigs
all: $(ALL)
checklib: checklib.o libpigpio.a checklib: checklib.o libpigpio.a
$(CC) -o checklib checklib.c -L. -lpigpio -lpthread -lrt $(CC) -o checklib checklib.c -L. -lpigpio -lpthread -lrt
@ -19,31 +21,29 @@ pig2vcd: pig2vcd.o
pigpiod: pigpiod.o libpigpio.a pigpiod: pigpiod.o libpigpio.a
$(CC) -o pigpiod pigpiod.c -L. -lpigpio -lpthread -lrt $(CC) -o pigpiod pigpiod.c -L. -lpigpio -lpthread -lrt
pigs: pigs.o command.o pigs: command.o
$(CC) -o pigs pigs.c command.c $(CC) -o pigs pigs.c command.c
.c.o:
$(CC) -c $(CFLAGS) $<
clean: clean:
rm -f *.o *.i *.s *~ libpigpio.a checklib demolib pigpiod pigs pig2vcd rm -f *.o *.i *.s *~ $(ALL)
install: $(LIB) install: $(LIB)
sudo install -m 0755 -d /usr/local/bin
sudo install -m 0755 -d /usr/local/include sudo install -m 0755 -d /usr/local/include
sudo install -m 0644 pigpio.h /usr/local/include
sudo install -m 0755 -d /usr/local/lib sudo install -m 0755 -d /usr/local/lib
sudo install -m 0644 libpigpio.a /usr/local/lib
sudo install -m 0755 -d /usr/local/bin
sudo install -m 0755 pig2vcd /usr/local/bin sudo install -m 0755 pig2vcd /usr/local/bin
sudo install -m 0755 pigpiod /usr/local/bin sudo install -m 0755 pigpiod /usr/local/bin
sudo install -m 0755 pigs /usr/local/bin sudo install -m 0755 pigs /usr/local/bin
sudo install -m 0644 pigpio.h /usr/local/include sudo python setup.py install
sudo install -m 0644 libpigpio.a /usr/local/lib
uninstall: uninstall:
sudo rm -f /usr/local/include/pigpio.h
sudo rm -f /usr/local/lib/libpigpio.a
sudo rm -f /usr/local/bin/pig2vcd sudo rm -f /usr/local/bin/pig2vcd
sudo rm -f /usr/local/bin/pigpiod sudo rm -f /usr/local/bin/pigpiod
sudo rm -f /usr/local/bin/pigs sudo rm -f /usr/local/bin/pigs
sudo rm -f /usr/local/include/pigpio.h
sudo rm -f /usr/local/lib/libpigpio.a
LIB = libpigpio.a LIB = libpigpio.a
OBJ = pigpio.o command.o OBJ = pigpio.o command.o
@ -53,11 +53,13 @@ $(LIB): $(OBJ)
$(RANLIB) $(LIB) $(RANLIB) $(LIB)
$(SIZE) $(LIB) $(SIZE) $(LIB)
# generated using gcc -M *.c
# DO NOT DELETE
checklib.o: checklib.c pigpio.h checklib.o: checklib.c pigpio.h
command.o: command.c pigpio.h command.h
demolib.o: demolib.c pigpio.h demolib.o: demolib.c pigpio.h
pig2vcd: pigpio.h pig2vcd.o: pig2vcd.c pigpio.h
pigpiod: pigpiod.c pigpio.h pigpio.o: pigpio.c pigpio.h command.h
pigs: pigs.c command.c pigpio.h command.h pigpiod.o: pigpiod.c pigpio.h command.h
pigs.o: pigs.c pigpio.h command.h

28
README
View File

@ -15,6 +15,7 @@ This will install:
the daemon (pigpiod) in /usr/local/bin the daemon (pigpiod) in /usr/local/bin
the socket interface (pigs) in /usr/local/bin the socket interface (pigs) in /usr/local/bin
the utility pig2vcd in /usr/local/bin the utility pig2vcd in /usr/local/bin
the Python module pigpio.py
TEST TEST
@ -22,8 +23,8 @@ To test the library do
sudo ./checklib sudo ./checklib
checklib.c, demolib.c, pig2vcd.c, pigpiod.c, and pigs.c show examples checklib.c, demolib.c, pig2vcd.c, pigpiod.c, pigs.c, and pigpio.py
of interfacing with the library. show examples of interfacing with the library.
DAEMON DAEMON
@ -59,9 +60,30 @@ cat /dev/pigerr &
echo "help" >/dev/pigpio echo "help" >/dev/pigpio
PYTHON INTERFACE
If the pigpiod daemon is running you can test the Python
interface by entering the following commands.
python
import pigpio
pigpio.start()
print(pigpio.get_current_tick())
print(hex(pigpio.read_bank_1()))
pigpio.stop()
help(pigpio)
quit()
STOP DAEMON STOP DAEMON
To stop the daemon To stop the pigpiod daemon
sudo killall pigpiod sudo killall pigpiod

View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 4+ This version is for pigpio version 7+
*/ */
#include <stdio.h> #include <stdio.h>
@ -141,7 +141,7 @@ static errInfo_t errInfo[]=
{PI_BAD_CLK_SOURCE , "clock source not 0-1"}, {PI_BAD_CLK_SOURCE , "clock source not 0-1"},
{PI_BAD_CLK_MICROS , "clock micros not 1, 2, 4, 5, 8, or 10"}, {PI_BAD_CLK_MICROS , "clock micros not 1, 2, 4, 5, 8, or 10"},
{PI_BAD_BUF_MILLIS , "buf millis not 100-10000"}, {PI_BAD_BUF_MILLIS , "buf millis not 100-10000"},
{PI_BAD_DUTY_RANGE , "dutycycle range not 25-40000"}, {PI_BAD_DUTYRANGE , "dutycycle range not 25-40000"},
{PI_BAD_SIGNUM , "signum not 0-63"}, {PI_BAD_SIGNUM , "signum not 0-63"},
{PI_BAD_PATHNAME , "can't open pathname"}, {PI_BAD_PATHNAME , "can't open pathname"},
{PI_NO_HANDLE , "no handle available"}, {PI_NO_HANDLE , "no handle available"},
@ -159,7 +159,8 @@ static errInfo_t errInfo[]=
{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_SOME_PERMITTED , "no permission to update one or more gpios"},
}; };
static char * fmtMdeStr="RW540123"; static char * fmtMdeStr="RW540123";
@ -289,4 +290,3 @@ char * cmdErrStr(int error)
} }
return "unknown error"; return "unknown error";
} }

View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 3+ This version is for pigpio version 7+
*/ */
#ifndef COMMAND_H #ifndef COMMAND_H
@ -39,10 +39,10 @@ This version is for pigpio version 3+
typedef struct typedef struct
{ {
int cmd; int cmd; /* command number */
char * name; char * name; /* command name */
int vt; int vt; /* command verification type */
int rv; int rv; /* command return value type */
} cmdInfo_t; } cmdInfo_t;
extern cmdInfo_t cmdInfo[]; extern cmdInfo_t cmdInfo[];

249
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 6 */ /* pigpio version 7 */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -229,6 +229,13 @@ bit 0 READ_LAST_NOT_SET_ERROR
} \ } \
while (0) while (0)
#define PERM_ERROR(format, arg...) \
do \
{ \
fprintf(stderr, "%s " format "\n", myTimeStamp(), ## arg); \
} \
while (0)
#define TIMER_ADD(a, b, result) \ #define TIMER_ADD(a, b, result) \
do \ do \
{ \ { \
@ -519,8 +526,6 @@ bit 0 READ_LAST_NOT_SET_ERROR
#define PI_WFRX_SERIAL 1 #define PI_WFRX_SERIAL 1
#define PI_WF_MICROS 2 #define PI_WF_MICROS 2
#define PI_WAVE_MAX_PULSES 3000
#define DATUMS 2000 #define DATUMS 2000
#define DEFAULT_PWM_IDX 5 #define DEFAULT_PWM_IDX 5
@ -704,12 +709,16 @@ static volatile gpioCfg_t gpioCfg =
static volatile gpioStats_t gpioStats; static volatile gpioStats_t gpioStats;
static int gpioMaskSet = 0;
/* initialise every gpioInitialise */ /* initialise every gpioInitialise */
static struct timespec libStarted; static struct timespec libStarted;
/* initialse if not libInitialised */ /* initialse if not libInitialised */
static uint64_t gpioMask;
static gpioPulse_t wf[3][PI_WAVE_MAX_PULSES]; static gpioPulse_t wf[3][PI_WAVE_MAX_PULSES];
static int wfc[3]={0, 0, 0}; static int wfc[3]={0, 0, 0};
@ -732,7 +741,6 @@ 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 unsigned hardwareRevision = 0;
static int pthAlertRunning = 0; static int pthAlertRunning = 0;
static int pthFifoRunning = 0; static int pthFifoRunning = 0;
@ -947,6 +955,7 @@ static uint32_t myGetTick(int pos)
static void myDoCommand(cmdCmd_t * cmd) static void myDoCommand(cmdCmd_t * cmd)
{ {
int p1, p2, res; int p1, p2, res;
uint32_t mask;
p1 = cmd->p1; p1 = cmd->p1;
p2 = cmd->p2; p2 = cmd->p2;
@ -956,7 +965,12 @@ static void myDoCommand(cmdCmd_t * cmd)
switch (cmd->cmd) switch (cmd->cmd)
{ {
case PI_CMD_MODES: case PI_CMD_MODES:
res = gpioSetMode(p1, p2); 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_MODEG: case PI_CMD_MODEG:
@ -964,7 +978,12 @@ static void myDoCommand(cmdCmd_t * cmd)
break; break;
case PI_CMD_PUD: case PI_CMD_PUD:
res = gpioSetPullUpDown(p1, p2); 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_READ: case PI_CMD_READ:
@ -972,23 +991,48 @@ static void myDoCommand(cmdCmd_t * cmd)
break; break;
case PI_CMD_WRITE: case PI_CMD_WRITE:
res = gpioWrite(p1, p2); 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_PWM: case PI_CMD_PWM:
res = gpioPWM(p1, p2); 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_PRS: case PI_CMD_PRS:
res = gpioSetPWMrange(p1, p2); 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_PFS: case PI_CMD_PFS:
res = gpioSetPWMfrequency(p1, p2); 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_SERVO: case PI_CMD_SERVO:
res = gpioServo(p1, p2); 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_WDOG: case PI_CMD_WDOG:
@ -1004,19 +1048,55 @@ static void myDoCommand(cmdCmd_t * cmd)
break; break;
case PI_CMD_BC1: case PI_CMD_BC1:
gpioWrite_Bits_0_31_Clear(p1); mask = gpioMask;
res = gpioWrite_Bits_0_31_Clear(p1&mask);
if ((mask | p1) != mask)
{
PERM_ERROR("gpioWrite_Bits_0_31_Clear: bad levels %08X (permissions %08X)",
p1, mask);
res = PI_SOME_PERMITTED;
}
break; break;
case PI_CMD_BC2: case PI_CMD_BC2:
gpioWrite_Bits_32_53_Clear(p1); mask = gpioMask>>32;
res = gpioWrite_Bits_32_53_Clear(p1&mask);
if ((mask | p1) != mask)
{
PERM_ERROR("gpioWrite_Bits_32_53_Clear: bad levels %08X (permissions %08X)",
p1, mask);
res = PI_SOME_PERMITTED;
}
break; break;
case PI_CMD_BS1: case PI_CMD_BS1:
gpioWrite_Bits_0_31_Set(p1); mask = gpioMask;
res = gpioWrite_Bits_0_31_Set(p1&mask);
if ((mask | p1) != mask)
{
PERM_ERROR("gpioWrite_Bits_0_31_Set: bad levels %08X (permissions %08X)",
p1, mask);
res = PI_SOME_PERMITTED;
}
break; break;
case PI_CMD_BS2: case PI_CMD_BS2:
gpioWrite_Bits_32_53_Set(p1); mask = gpioMask>>32;
res = gpioWrite_Bits_32_53_Set(p1&mask);
if ((mask | p1) != mask)
{
PERM_ERROR("gpioWrite_Bits_32_53_Set: bad levels %08X (permissions %08X)",
p1, mask);
res = PI_SOME_PERMITTED;
}
break; break;
case PI_CMD_TICK: case PI_CMD_TICK:
@ -1274,7 +1354,7 @@ static void waveCbOPrint(int pos)
p = waveCbVOadr(pos); p = waveCbVOadr(pos);
fprintf(stderr, "i=%lx s=%lx d=%lx len=%lx s=%lx nxt=%lx", fprintf(stderr, "i=%lx s=%lx d=%lx len=%lx s=%lx nxt=%lx\n",
p->info, p->src, p->dst, p->length, p->stride, p->next); p->info, p->src, p->dst, p->length, p->stride, p->next);
} }
@ -1669,7 +1749,7 @@ static void dmaCbPrint(int pos)
p = dmaCB2adr(pos); p = dmaCB2adr(pos);
fprintf(stderr, "i=%lx s=%lx d=%lx len=%lx s=%lx nxt=%lx", fprintf(stderr, "i=%lx s=%lx d=%lx len=%lx s=%lx nxt=%lx\n",
p->info, p->src, p->dst, p->length, p->stride, p->next); p->info, p->src, p->dst, p->length, p->stride, p->next);
} }
@ -1962,13 +2042,15 @@ static void sigHandler(int signum)
DBG(DBG_USER, "Debug level %d\n", gpioCfg.dbgLevel); DBG(DBG_USER, "Debug level %d\n", gpioCfg.dbgLevel);
} }
else if (signum == SIGPIPE)
{
DBG(DBG_USER, "SIGPIPE received");
}
else else
{ {
/* close library safely and exit */ /* exit */
DBG(DBG_USER, "Unhandled signal %d, terminating\n", signum); DBG(DBG_MIN_LEVEL, "Unhandled signal %d, terminating\n", signum);
gpioTerminate();
exit(-1); exit(-1);
} }
@ -1976,11 +2058,9 @@ static void sigHandler(int signum)
} }
else else
{ {
/* close library safely and exit */ /* exit */
DBG(DBG_USER, "Unhandled signal %d, terminating\n", signum); DBG(DBG_MIN_LEVEL, "Unhandled signal %d, terminating\n", signum);
gpioTerminate();
exit(-1); exit(-1);
} }
@ -2424,7 +2504,6 @@ static void * pthTimerTick(void *x)
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
@ -2465,6 +2544,7 @@ static void * pthFifoThread(void *x)
break; break;
case 1: case 1:
fprintf(outFifo, "%d\n", cmd.res);
break; break;
case 2: case 2:
@ -2860,7 +2940,7 @@ static int initDMAcbs(void)
/* allocate memory for pointers to virtual and physical pages */ /* allocate memory for pointers to virtual and physical pages */
dmaBloc = mmap( dmaBloc = mmap(
0, (bufferBlocks+1)*sizeof(dmaPage_t *), 0, (bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *),
PROT_READ|PROT_WRITE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED,
-1, 0); -1, 0);
@ -2869,7 +2949,7 @@ static int initDMAcbs(void)
SOFT_ERROR(PI_INIT_FAILED, "mmap dma virtual failed (%m)"); SOFT_ERROR(PI_INIT_FAILED, "mmap dma virtual failed (%m)");
dmaVirt = mmap( dmaVirt = mmap(
0, PAGES_PER_BLOCK*(bufferBlocks+1)*sizeof(dmaPage_t *), 0, PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *),
PROT_READ|PROT_WRITE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED,
-1, 0); -1, 0);
@ -2878,7 +2958,7 @@ static int initDMAcbs(void)
SOFT_ERROR(PI_INIT_FAILED, "mmap dma virtual failed (%m)"); SOFT_ERROR(PI_INIT_FAILED, "mmap dma virtual failed (%m)");
dmaPhys = mmap( dmaPhys = mmap(
0, PAGES_PER_BLOCK*(bufferBlocks+1)*sizeof(dmaPage_t *), 0, PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *),
PROT_READ|PROT_WRITE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED,
-1, 0); -1, 0);
@ -2901,7 +2981,7 @@ static int initDMAcbs(void)
if (pagemapFd < 0) if (pagemapFd < 0)
SOFT_ERROR(PI_INIT_FAILED, "open pagemap failed(%m)"); SOFT_ERROR(PI_INIT_FAILED, "open pagemap failed(%m)");
for (i=0; i<(bufferBlocks+1); i++) initDMAblock(pagemapFd, i); for (i=0; i<(bufferBlocks+PI_WAVE_BLOCKS); i++) initDMAblock(pagemapFd, i);
close(pagemapFd); close(pagemapFd);
@ -2918,7 +2998,10 @@ static int initDMAcbs(void)
dmaInitCbs(); dmaInitCbs();
if (gpioCfg.dbgLevel >= DBG_DMACBS) if (gpioCfg.dbgLevel >= DBG_DMACBS)
{
fprintf(stderr, "*** INPUT DMA CONTROL BLOCKS ***\n");
for (i=0; i<NUM_CBS; i++) dmaCbPrint(i); for (i=0; i<NUM_CBS; i++) dmaCbPrint(i);
}
return 0; return 0;
} }
@ -3132,7 +3215,6 @@ static void initClearGlobals(void)
libInitialised = 0; libInitialised = 0;
DMAstarted = 0; DMAstarted = 0;
hardwareRevision = 0;
pthAlertRunning = 0; pthAlertRunning = 0;
pthFifoRunning = 0; pthFifoRunning = 0;
@ -3224,37 +3306,6 @@ static void initClearGlobals(void)
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static unsigned initHardwareRevision(void)
{
FILE * filp;
unsigned rev;
char buf[512];
char term;
rev = 0;
filp = fopen ("/proc/cpuinfo", "r");
if (filp != NULL)
{
while (fgets(buf, sizeof(buf), filp) != NULL)
{
if (!strncasecmp("revision\t", buf, 9))
{
if (sscanf(buf+strlen(buf)-5, "%x%c", &rev, &term) == 2)
{
if (term == '\n') break;
rev = 0;
}
}
}
fclose(filp);
}
return rev;
}
/* ----------------------------------------------------------------------- */
static void initReleaseResources(void) static void initReleaseResources(void)
{ {
int i; int i;
@ -3314,36 +3365,36 @@ static void initReleaseResources(void)
if (dmaVirt != MAP_FAILED) if (dmaVirt != MAP_FAILED)
{ {
for (i=0; i<PAGES_PER_BLOCK*(bufferBlocks+1); i++) for (i=0; i<PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS); i++)
{ {
munmap(dmaVirt[i], PAGE_SIZE); munmap(dmaVirt[i], PAGE_SIZE);
} }
munmap(dmaVirt, PAGES_PER_BLOCK*(bufferBlocks+1)*sizeof(dmaPage_t *)); munmap(dmaVirt, PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *));
} }
dmaVirt = MAP_FAILED; dmaVirt = MAP_FAILED;
if (dmaPhys != MAP_FAILED) if (dmaPhys != MAP_FAILED)
{ {
for (i=0; i<PAGES_PER_BLOCK*(bufferBlocks+1); i++) for (i=0; i<PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS); i++)
{ {
munmap(dmaPhys[i], PAGE_SIZE); munmap(dmaPhys[i], PAGE_SIZE);
} }
munmap(dmaPhys, PAGES_PER_BLOCK*(bufferBlocks+1)*sizeof(dmaPage_t *)); munmap(dmaPhys, PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *));
} }
dmaPhys = MAP_FAILED; dmaPhys = MAP_FAILED;
if (dmaBloc != MAP_FAILED) if (dmaBloc != MAP_FAILED)
{ {
for (i=0; i<(bufferBlocks+1); i++) for (i=0; i<(bufferBlocks+PI_WAVE_BLOCKS); i++)
{ {
munmap(dmaBloc[i], PAGES_PER_BLOCK*PAGE_SIZE); munmap(dmaBloc[i], PAGES_PER_BLOCK*PAGE_SIZE);
} }
munmap(dmaBloc, (bufferBlocks+1)*sizeof(dmaPage_t *)); munmap(dmaBloc, (bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *));
} }
dmaBloc = MAP_FAILED; dmaBloc = MAP_FAILED;
@ -3403,6 +3454,17 @@ int gpioInitialise(void)
if (fdLock < 0) if (fdLock < 0)
SOFT_ERROR(PI_INIT_FAILED, "Can't lock %s", PI_LOCKFILE); SOFT_ERROR(PI_INIT_FAILED, "Can't lock %s", PI_LOCKFILE);
if (!gpioMaskSet)
{
i = gpioHardwareRevision();
if (i == 0) gpioMask = PI_DEFAULT_UPDATE_MASK_R0;
else if (i < 4) gpioMask = PI_DEFAULT_UPDATE_MASK_R1;
else gpioMask = PI_DEFAULT_UPDATE_MASK_R2;
gpioMaskSet = 1;
}
sigSetHandler(); sigSetHandler();
if (initPeripherals() < 0) return PI_INIT_FAILED; if (initPeripherals() < 0) return PI_INIT_FAILED;
@ -3450,8 +3512,6 @@ int gpioInitialise(void)
pthSocketRunning = 1; pthSocketRunning = 1;
} }
hardwareRevision = initHardwareRevision();
initDMAgo((uint32_t *)dmaIn, (uint32_t)dmaIPhys[0]); initDMAgo((uint32_t *)dmaIn, (uint32_t)dmaIPhys[0]);
return PIGPIO_VERSION; return PIGPIO_VERSION;
@ -3465,6 +3525,7 @@ void gpioTerminate(void)
DBG(DBG_USER, ""); DBG(DBG_USER, "");
gpioMaskSet = 0;
if (libInitialised) if (libInitialised)
{ {
@ -3716,7 +3777,7 @@ int gpioSetPWMrange(unsigned gpio, unsigned range)
SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio); SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
if ((range < PI_MIN_DUTYCYCLE_RANGE) || (range > PI_MAX_DUTYCYCLE_RANGE)) if ((range < PI_MIN_DUTYCYCLE_RANGE) || (range > PI_MAX_DUTYCYCLE_RANGE))
SOFT_ERROR(PI_BAD_DUTY_RANGE, "gpio %d, bad range (%d)", gpio, range); SOFT_ERROR(PI_BAD_DUTYRANGE, "gpio %d, bad range (%d)", gpio, range);
oldWidth = gpioInfo[gpio].width; oldWidth = gpioInfo[gpio].width;
@ -4247,7 +4308,10 @@ int gpioWaveTxStart(unsigned mode)
cb = wave2Cbs(mode); cb = wave2Cbs(mode);
if (gpioCfg.dbgLevel >= DBG_SLOW_TICK) if (gpioCfg.dbgLevel >= DBG_SLOW_TICK)
{
fprintf(stderr, "*** OUTPUT DMA CONTROL BLOCKS ***\n");
for (i=0; i<cb; i++) waveCbOPrint(i); for (i=0; i<cb; i++) waveCbOPrint(i);
}
initDMAgo((uint32_t *)dmaOut, (uint32_t)dmaOPhys[0]); initDMAgo((uint32_t *)dmaOut, (uint32_t)dmaOPhys[0]);
@ -4899,11 +4963,34 @@ uint32_t gpioTick(void)
unsigned gpioHardwareRevision(void) unsigned gpioHardwareRevision(void)
{ {
static unsigned rev = 0;
FILE * filp;
char buf[512];
char term;
DBG(DBG_USER, ""); DBG(DBG_USER, "");
CHECK_INITED; if (rev) return rev;
return hardwareRevision; filp = fopen ("/proc/cpuinfo", "r");
if (filp != NULL)
{
while (fgets(buf, sizeof(buf), filp) != NULL)
{
if (!strncasecmp("revision\t", buf, 9))
{
if (sscanf(buf+strlen(buf)-5, "%x%c", &rev, &term) == 2)
{
if (term == '\n') break;
rev = 0;
}
}
}
fclose(filp);
}
return rev;
} }
@ -4994,6 +5081,22 @@ int gpioCfgDMAchannels(unsigned primaryChannel, unsigned secondaryChannel)
} }
/*-------------------------------------------------------------------------*/
int gpioCfgPermissions(uint64_t updateMask)
{
DBG(DBG_USER, "gpio update mask=%llX", updateMask);
CHECK_NOT_INITED;
gpioMask = updateMask;
gpioMaskSet = 1;
return 0;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
int gpioCfgInterfaces(unsigned ifFlags) int gpioCfgInterfaces(unsigned ifFlags)

View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 6 This version is for pigpio version 7
*/ */
#ifndef PIGPIO_H #ifndef PIGPIO_H
@ -82,7 +82,7 @@ This version is for pigpio version 6
#include <stdint.h> #include <stdint.h>
#define PIGPIO_VERSION 6 #define PIGPIO_VERSION 7
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -175,7 +175,9 @@ gpioHardwareRevision Get hardware version.
gpioCfgBufferSize Configure the gpio sample buffer size. gpioCfgBufferSize Configure the gpio sample buffer size.
gpioCfgClock Configure the gpio sample rate. gpioCfgClock Configure the gpio sample rate.
gpioCfgDMAchannel Configure the DMA channel. gpioCfgDMAchannel Configure the DMA channel (DEPRECATED).
gpioCfgDMAchannels Configure the DMA channels.
gpioCfgPermissions Configure the gpio access permissions.
gpioCfgInterfaces Configure user interfaces. gpioCfgInterfaces Configure user interfaces.
gpioCfgSocketPort Configure socket port. gpioCfgSocketPort Configure socket port.
@ -482,7 +484,7 @@ int gpioSetPWMrange(unsigned user_gpio,
to gpioPWM will use a dutycycle between 0 (off) and range (fully on). to gpioPWM will use a dutycycle between 0 (off) and range (fully on).
Returns the real range for the given gpio's frequency if OK, Returns the real range for the given gpio's frequency if OK,
otherwise PI_BAD_USER_GPIO or PI_BAD_DUTY_RANGE. otherwise PI_BAD_USER_GPIO or PI_BAD_DUTYRANGE.
EXAMPLE: EXAMPLE:
... ...
@ -892,9 +894,12 @@ int gpioWaveAddSerial(unsigned user_gpio,
the same waveform. the same waveform.
*/ */
#define PI_WAVE_BLOCKS 3
#define PI_WAVE_MAX_PULSES (PI_WAVE_BLOCKS * 3000)
#define PI_WAVE_MAX_CHARS (PI_WAVE_BLOCKS * 256)
#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_CHARS 256
@ -1601,7 +1606,7 @@ int gpioCfgClock(unsigned micros,
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int gpioCfgDMAchannel(unsigned channel); int gpioCfgDMAchannel(unsigned channel); /* DEPRECATED */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* Configures pigpio to use the specified DMA channel. /* Configures pigpio to use the specified DMA channel.
@ -1622,7 +1627,7 @@ int gpioCfgDMAchannels(unsigned primaryChannel,
/* Configures pigpio to use the specified DMA channels. /* Configures pigpio to use the specified DMA channels.
The default setting is to use channel 14 for the primary channel and The default setting is to use channel 14 for the primary channel and
channel 6 for the secondary channel. channel 5 for the secondary channel.
*/ */
#define PI_MAX_PRIMARY_CHANNEL 14 #define PI_MAX_PRIMARY_CHANNEL 14
@ -1630,6 +1635,18 @@ int gpioCfgDMAchannels(unsigned primaryChannel,
/*-------------------------------------------------------------------------*/
int gpioCfgPermissions(uint64_t updateMask);
/*-------------------------------------------------------------------------*/
/* Configures pigpio to only allow updates (writes or mode changes) for the
gpios specified by the mask.
The default setting is to allow updates to gpios 0-31, i.e. an update mask
of 0x00000000FFFFFFFF.
*/
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int gpioCfgSocketPort(unsigned port); int gpioCfgSocketPort(unsigned port);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -1746,7 +1763,8 @@ after this command is issued.
#define PI_BAD_CLK_SOURCE -18 /* clock source not 0-1 */ #define PI_BAD_CLK_SOURCE -18 /* clock source not 0-1 */
#define PI_BAD_CLK_MICROS -19 /* clock micros not 1, 2, 4, 5, 8, or 10 */ #define PI_BAD_CLK_MICROS -19 /* clock micros not 1, 2, 4, 5, 8, or 10 */
#define PI_BAD_BUF_MILLIS -20 /* buf millis not 100-10000 */ #define PI_BAD_BUF_MILLIS -20 /* buf millis not 100-10000 */
#define PI_BAD_DUTY_RANGE -21 /* dutycycle range not 25-40000 */ #define PI_BAD_DUTYRANGE -21 /* dutycycle range not 25-40000 */
#define PI_BAD_DUTY_RANGE -21 /* DEPRECATED (use PI_BAD_DUTYRANGE) */
#define PI_BAD_SIGNUM -22 /* signum not 0-63 */ #define PI_BAD_SIGNUM -22 /* signum not 0-63 */
#define PI_BAD_PATHNAME -23 /* can't open pathname */ #define PI_BAD_PATHNAME -23 /* can't open pathname */
#define PI_NO_HANDLE -24 /* no handle available */ #define PI_NO_HANDLE -24 /* no handle available */
@ -1767,6 +1785,8 @@ after this command is issued.
#define PI_NOT_SERIAL_GPIO -38 /* no serial read in progress on gpio */ #define PI_NOT_SERIAL_GPIO -38 /* no serial read in progress on gpio */
#define PI_BAD_SERIAL_STRUC -39 /* bad null serial structure parameter */ #define PI_BAD_SERIAL_STRUC -39 /* bad null serial structure parameter */
#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_SOME_PERMITTED -42 /* one or more gpios not permitted */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -1778,8 +1798,12 @@ after this command is issued.
#define PI_DEFAULT_IF_FLAGS 0 #define PI_DEFAULT_IF_FLAGS 0
#define PI_DEFAULT_DMA_CHANNEL 14 #define PI_DEFAULT_DMA_CHANNEL 14
#define PI_DEFAULT_DMA_PRIMARY_CHANNEL 14 #define PI_DEFAULT_DMA_PRIMARY_CHANNEL 14
#define PI_DEFAULT_DMA_SECONDARY_CHANNEL 6 #define PI_DEFAULT_DMA_SECONDARY_CHANNEL 5
#define PI_DEFAULT_SOCKET_PORT 8888 #define PI_DEFAULT_SOCKET_PORT 8888
#define PI_DEFAULT_SOCKET_PORT_STR "8888"
#define PI_DEFAULT_SOCKET_ADDR_STR "127.0.0.1"
#define PI_DEFAULT_UPDATE_MASK_R0 0xFBE6CF9F
#define PI_DEFAULT_UPDATE_MASK_R1 0x03E6CF93
#define PI_DEFAULT_UPDATE_MASK_R2 0xFBC6CF9C
#endif #endif

1591
pigpio.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 4+ This version is for pigpio version 7+
*/ */
#include <sys/types.h> #include <sys/types.h>
@ -54,8 +54,10 @@ static unsigned clockMicros = PI_DEFAULT_CLK_MICROS;
static unsigned clockPeripheral = PI_DEFAULT_CLK_PERIPHERAL; static unsigned clockPeripheral = PI_DEFAULT_CLK_PERIPHERAL;
static unsigned clockSource = PI_DEFAULT_CLK_SOURCE; static unsigned clockSource = PI_DEFAULT_CLK_SOURCE;
static unsigned ifFlags = PI_DEFAULT_IF_FLAGS; static unsigned ifFlags = PI_DEFAULT_IF_FLAGS;
static unsigned DMAchannelChannel = PI_DEFAULT_DMA_CHANNEL; static unsigned DMAprimaryChannel = PI_DEFAULT_DMA_PRIMARY_CHANNEL;
static unsigned DMAsecondaryChannel = PI_DEFAULT_DMA_SECONDARY_CHANNEL;
static unsigned socketPort = PI_DEFAULT_SOCKET_PORT; static unsigned socketPort = PI_DEFAULT_SOCKET_PORT;
static uint64_t updateMask = -1;
static FILE * errFifo; static FILE * errFifo;
@ -64,13 +66,15 @@ void usage()
fprintf(stderr, "\n" \ fprintf(stderr, "\n" \
"Usage: sudo pigpiod [OPTION] ...\n" \ "Usage: sudo pigpiod [OPTION] ...\n" \
" -b value, gpio sample buffer in milliseconds, default 120\n" \ " -b value, gpio sample buffer in milliseconds, default 120\n" \
" -d value, DMA channel, 0-14, default 14\n" \ " -d value, primary DMA channel, 0-14, default 14\n" \
" -e value, secondary DMA channel, 0-6, default 5\n" \
" -f, disable fifo interface, default enabled\n" \ " -f, disable fifo interface, default enabled\n" \
" -k, disable socket interface, default enabled\n" \ " -k, disable socket interface, default enabled\n" \
" -p value, socket port, 1024-32000, default 8888\n" \ " -p value, socket port, 1024-32000, default 8888\n" \
" -s value, sample rate, 1, 2, 4, 5, 8, or 10, default 5\n" \ " -s value, sample rate, 1, 2, 4, 5, 8, or 10, default 5\n" \
" -t value, clock peripheral, 0=PWM 1=PCM, default PCM\n" \ " -t value, clock peripheral, 0=PWM 1=PCM, default PCM\n" \
" -u value, clock source, 0=OSC 1=PLLD, default PLLD\n" \ " -u value, clock source, 0=OSC 1=PLLD, default PLLD\n" \
" -x mask, gpios which may be updated, default 0xFFFFFFFF\n" \
"EXAMPLE\n" \ "EXAMPLE\n" \
"sudo pigpiod -s 2 -b 200 -f\n" \ "sudo pigpiod -s 2 -b 200 -f\n" \
" Set a sample rate of 2 microseconds with a 200 millisecond\n" \ " Set a sample rate of 2 microseconds with a 200 millisecond\n" \
@ -81,8 +85,10 @@ void usage()
static void initOpts(int argc, char *argv[]) static void initOpts(int argc, char *argv[])
{ {
int i, opt; int i, opt;
uint64_t mask;
char * endptr;
while ((opt = getopt(argc, argv, "b:d:fkp:s:t:u:")) != -1) while ((opt = getopt(argc, argv, "b:d:e:fkp:s:t:u:x:")) != -1)
{ {
i = -1; i = -1;
@ -97,11 +103,18 @@ static void initOpts(int argc, char *argv[])
case 'd': case 'd':
i = atoi(optarg); i = atoi(optarg);
if ((i >= PI_MIN_DMA_CHANNEL) && (i <= PI_MAX_DMA_CHANNEL)) if ((i >= PI_MIN_DMA_CHANNEL) && (i <= PI_MAX_PRIMARY_CHANNEL))
DMAchannelChannel = i; DMAprimaryChannel = i;
else cmdFatal("invalid -d option (%d)", i); else cmdFatal("invalid -d option (%d)", i);
break; break;
case 'e':
i = atoi(optarg);
if ((i >= PI_MIN_DMA_CHANNEL) && (i <= PI_MAX_SECONDARY_CHANNEL))
DMAsecondaryChannel = i;
else cmdFatal("invalid -e option (%d)", i);
break;
case 'f': case 'f':
ifFlags |= PI_DISABLE_FIFO_IF; ifFlags |= PI_DISABLE_FIFO_IF;
break; break;
@ -151,6 +164,13 @@ static void initOpts(int argc, char *argv[])
else cmdFatal("invalid -u option (%d)", i); else cmdFatal("invalid -u option (%d)", i);
break; break;
case 'x':
mask = strtoll(optarg, &endptr, 0);
printf("mask=%llx\n", mask);
if (!*endptr) updateMask = mask;
else cmdFatal("invalid -x option (%s)", optarg);
break;
default: /* '?' */ default: /* '?' */
usage(); usage();
exit(-1); exit(-1);
@ -224,10 +244,12 @@ int main(int argc, char **argv)
gpioCfgInterfaces(ifFlags); gpioCfgInterfaces(ifFlags);
gpioCfgDMAchannel(DMAchannelChannel); gpioCfgDMAchannels(DMAprimaryChannel, DMAsecondaryChannel);
gpioCfgSocketPort(socketPort); gpioCfgSocketPort(socketPort);
if (updateMask != -1) gpioCfgPermissions(updateMask);
/* start library */ /* start library */
if (gpioInitialise()< 0) cmdFatal("Can't initialise pigpio library"); if (gpioInitialise()< 0) cmdFatal("Can't initialise pigpio library");
@ -275,4 +297,3 @@ int main(int argc, char **argv)
return 0; return 0;
} }

65
pigs.c
View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 3+ This version is for pigpio version 7+
*/ */
#include <stdio.h> #include <stdio.h>
@ -34,6 +34,8 @@ This version is for pigpio version 3+
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include "pigpio.h" #include "pigpio.h"
@ -44,32 +46,55 @@ This program provides a socket interface
to the commands available from pigpio. to the commands available from pigpio.
*/ */
int main(int argc , char *argv[]) static int openSocket(void)
{ {
int sock, r, idx, port; int sock, err;
struct sockaddr_in server; struct addrinfo hints, *res, *rp;
cmdCmd_t cmd; const char *addrStr, *portStr;
char * portStr, * addrStr;
char buf[128];
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock != -1)
{
portStr = getenv(PI_ENVPORT); portStr = getenv(PI_ENVPORT);
if (portStr) port = atoi(portStr); if (!portStr) portStr = PI_DEFAULT_SOCKET_PORT_STR;
else port = PI_DEFAULT_SOCKET_PORT;
addrStr = getenv(PI_ENVADDR); addrStr = getenv(PI_ENVADDR);
if (!addrStr) addrStr="127.0.0.1"; if (!addrStr) addrStr = PI_DEFAULT_SOCKET_ADDR_STR;
server.sin_addr.s_addr = inet_addr(addrStr); memset (&hints, 0, sizeof (hints));
server.sin_family = AF_INET;
server.sin_port = htons(port);
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == 0) hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME;
err = getaddrinfo(addrStr, portStr, &hints, &res);
if (err) return -1;
for (rp=res; rp!=NULL; rp=rp->ai_next)
{
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sock == -1) continue;
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) break;
}
freeaddrinfo(res);
if (rp == NULL) return -1;
return sock;
}
int main(int argc , char *argv[])
{
int sock, r, idx;
cmdCmd_t cmd;
char buf[128];
sock = openSocket();
if (sock != -1)
{ {
switch(argc) switch(argc)
{ {
@ -106,6 +131,8 @@ int main(int argc , char *argv[])
break; break;
case 1: case 1:
r = cmd.res;
if (r < 0) cmdFatal("ERROR: %s", cmdErrStr(r));
break; break;
case 2: case 2:
@ -136,8 +163,6 @@ int main(int argc , char *argv[])
else cmdFatal("connect failed, %m"); else cmdFatal("connect failed, %m");
close(sock); close(sock);
}
else cmdFatal("socket failed, %m");
return 0; return 0;
} }

12
setup.py Normal file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env python
from distutils.core import setup
setup(name='pigpio',
version='1.0',
description='Raspberry Pi gpio utility',
author='joan',
author_email='joan@abyz.me.uk',
url='http://abyz.co.uk/rpi/pigpio/python.html/',
py_modules=['pigpio']
)