diff --git a/MakeRemote b/MakeRemote
index c27fc64..0e3f83a 100644
--- a/MakeRemote
+++ b/MakeRemote
@@ -5,9 +5,9 @@ SIZE = size
CFLAGS = -O3 -Wall
-ALL = libpigpiod_if.a pigs pigpio.py setup.py
+ALL = libpigpiod_if.a pigs
-all: $(ALL)
+all: $(ALL) pigpio.py setup.py
pigs: command.o pigs.o
$(CC) -o pigs pigs.c command.c
diff --git a/command.c b/command.c
index a128a9d..757b082 100644
--- a/command.c
+++ b/command.c
@@ -26,7 +26,7 @@ For more information, please refer to
*/
/*
-This version is for pigpio version 11+
+This version is for pigpio version 12+
*/
#include
@@ -46,6 +46,7 @@ This version is for pigpio version 11+
3 %08X %08X
4 %u %u
5 HELP HELP
+6 %s <0 ERR
*/
/* vfyt
@@ -58,6 +59,7 @@ This version is for pigpio version 11+
8 MODES %d %c
9 PUD %d %c
10 PROG %s
+11 WVAS %d %d %d %s
*/
cmdInfo_t cmdInfo[]=
@@ -98,6 +100,9 @@ cmdInfo_t cmdInfo[]=
{PI_CMD_READ, "READ", 2, 2, 0},
{PI_CMD_SERVO, "S", 3, 0, 0},
{PI_CMD_SERVO, "SERVO", 3, 0, 0},
+ {PI_CMD_SLR, "SLR", 3, 6, 0},
+ {PI_CMD_SLRC, "SLRC", 2, 2, 0},
+ {PI_CMD_SLRO, "SLRO", 3, 2, 0},
{PI_CMD_WDOG, "WDOG", 3, 0, 0},
{PI_CMD_WRITE, "W", 3, 0, 0},
{PI_CMD_WRITE, "WRITE", 3, 0, 0},
@@ -116,68 +121,72 @@ cmdInfo_t cmdInfo[]=
};
char * cmdUsage = "\
-BC1 x clear gpios in bank 1\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\
-BS2 x set gpios in bank 2\n\
-H displays command help\n\
-HELP displays command help\n\
-HWVER return hardware version\n\
-M g m set gpio mode\n\
-MG g get gpio mode\n\
-MODEG g get gpio mode\n\
-MODES g m set gpio mode\n\
-NB h x start notification\n\
-NC h close notification\n\
-NO request notification handle\n\
-NP h pause notification\n\
-P u d set PWM value 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\
-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\
-PRS u d set PWM range for gpio\n\
-PUD g p set gpio pull up/down\n\
-PWM u d set PWM value for gpio\n\
-R g read 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\
-WRITE g l write level to gpio\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\
-b = baud rate\n\
-d = decimal value\n\
-g = gpio (0-53)\n\
-h = handle (0-31)\n\
-l = level (0-1)\n\
-m = mode (RW540123)\n\
-p = pud (ODU)\n\
-pl = pulse length (0-100)\n\
-s = script id\n\
-t = text\n\
-u = user gpio (0-31)\n\
-x = hex value\n\
+BC1 x Clear gpios x in bank 1.\n\
+BC2 x Clear gpios x in bank 2.\n\
+BR1 Read gpios bank 1.\n\
+BR2 Read gpios bank 2.\n\
+BS1 x Set gpios x in bank 1.\n\
+BS2 x Set gpios x in bank 2.\n\
+H Displays command help.\n\
+HELP Displays command help.\n\
+HWVER Return hardware version.\n\
+M g m Set gpio g to mode m.\n\
+MG g Get gpio g mode.\n\
+MODEG g Get gpio g mode.\n\
+MODES g m Set gpio g to mode m.\n\
+NB h x Start notifications on handle h with x.\n\
+NC h Close notification handle h.\n\
+NO Request notification handle.\n\
+NP h Pause notifications on handle h.\n\
+P u d Set PWM value for user gpio u to d.\n\
+PFG u Get PWM frequency for user gpio u.\n\
+PFS u d Set PWM frequency for user gpio u to d.\n\
+PIGPV Return pigpio version.\n\
+PRG u Get PWM range for user gpio u.\n\
+PROC t Store text t of script.\n\
+PROCD s Delete script s.\n\
+PROCR s Run script s.\n\
+PROCS s Stop script s.\n\
+PRRG u Get PWM real range for user gpio u.\n\
+PRS u d Set PWM range for user gpio u to d.\n\
+PUD g p Set gpio pull up/down for gpio g to p.\n\
+PWM u d Set PWM value for user gpio u to d.\n\
+R g Read gpio g.\n\
+READ g Read gpio g.\n\
+S u d Set servo value for user gpio u to d microseconds.\n\
+SERVO u d Set servo value for user gpio u to d microseconds.\n\
+SLR u d Read up to d bytes of serial data from user gpio u.\n\
+SLRC u Close user gpio u for serial data.\n\
+SLRO u b Open user gpio u for serial data at b baud.\n\
+T Return current tick.\n\
+TICK Return current tick.\n\
+TRIG u pl L Trigger level L for pl micros on user gpio u.\n\
+W g L Write level L to gpio g.\n\
+WDOG u d Set watchdog of d milliseconds on user gpio u.\n\
+WRITE g L Write level L to gpio g.\n\
+WVAS u b o t Wave add serial data t to user gpio u at b baud.\n\
+WVBSY Check if wave busy.\n\
+WVCLR Wave clear.\n\
+WVGO Wave transmit.\n\
+WVGOR Wave transmit repeatedly.\n\
+WVHLT Wave stop.\n\
+WVSC ws Wave get DMA control block stats.\n\
+WVSM ws Wave get micros stats.\n\
+WVSP ws Wave get pulses stats.\n\
+.\n\
+b = baud rate.\n\
+d = decimal value.\n\
+g = gpio (0-53).\n\
+h = handle (0-31).\n\
+L = level (0-1).\n\
+m = mode (RW540123).\n\
+o = offset (0-).\n\
+p = pud (ODU).\n\
+pl = pulse length (0-100).\n\
+s = script id.\n\
+t = text.\n\
+u = user gpio (0-31).\n\
+x = hex value.\n\
";
typedef struct
@@ -237,6 +246,8 @@ static errInfo_t errInfo[]=
{PI_BAD_SCRIPT , "invalid script"},
{PI_BAD_SCRIPT_ID , "unknown script id"},
{PI_BAD_SER_OFFSET , "add serial data offset > 30 minute"},
+ {PI_GPIO_IN_USE , "gpio already in use"},
+ {PI_BAD_SERIAL_COUNT , "must read at least a byte at a time"},
};
static char * fmtMdeStr="RW540123";
@@ -256,7 +267,7 @@ static int cmdMatch(char * str)
int cmdParse(char *buf, cmdCmd_t *cmd, int argc, char *argv[], gpioExtent_t *ext)
{
char str[8];
- int f, valid, idx, val;
+ int f, valid, idx, val, p;
char *ptr;
char c, t;
@@ -276,21 +287,21 @@ int cmdParse(char *buf, cmdCmd_t *cmd, int argc, char *argv[], gpioExtent_t *ext
switch (cmdInfo[idx].vt)
{
- case 1: /* BR1 BR2 HWVER NO PIGPV TICK WVBSY WVCLR WVGO WVGOR
- WVHLT
+ case 1: /* BR1 BR2 HWVER NO PIGPV TICK WVBSY WVCLR WVGO
+ WVGOR WVHLT
*/
f = sscanf(buf, " %7s %c", str, &t);
if (f == 1) valid = 1;
break;
- case 2: /* MODEG NC NP PFG PRG PROCD PROCR PROCS PRRG READ
- WVSC WVSM WVSP
+ case 2: /* MODEG NC NP PFG PRG PROCD PROCR PROCS PRRG
+ SLRC READ WVSC WVSM WVSP
*/
f = sscanf(buf, " %7s %d %c", str, &cmd->p1, &t);
if (f == 2) valid = 1;
break;
- case 3: /* PFS PRS PWM SERVO WDOG WRITE
+ case 3: /* PFS PRS PWM SERVO SLR SLRO WDOG WRITE
*/
f = sscanf(buf, " %7s %d %d %c", str, &cmd->p1, &cmd->p2, &t);
if (f == 3) valid = 1;
@@ -308,7 +319,7 @@ int cmdParse(char *buf, cmdCmd_t *cmd, int argc, char *argv[], gpioExtent_t *ext
str, &cmd->p1, &cmd->p2, &ext[0].data, &t);
if (f == 4)
{
- ext[0].n = sizeof(unsigned);
+ ext[0].size = sizeof(unsigned);
ext[0].ptr = &ext[0].data;
valid = 1;
}
@@ -319,7 +330,7 @@ int cmdParse(char *buf, cmdCmd_t *cmd, int argc, char *argv[], gpioExtent_t *ext
valid = 1;
break;
- case 7: /* BC1 BC2 BS1 BS2
+ case 7: /* BC1 BC2 BS1 BS2
*/
f = sscanf(buf, " %7s %x %c", str, &cmd->p1, &t);
if (f == 2) valid = 1;
@@ -359,38 +370,56 @@ int cmdParse(char *buf, cmdCmd_t *cmd, int argc, char *argv[], gpioExtent_t *ext
case 10: /* PROC
*/
- if (argc == 3)
+ if ((argc == 0) || (argc == 3))
{
- cmd->p1 = strlen(argv[2]);
- ext[0].n = cmd->p1;
- ext[0].ptr = argv[2];
+ if (argc == 3)
+ {
+ cmd->p1 = strlen(argv[2]);
+ ext[0].ptr = argv[2];
+ }
+ else /* pipe i/f */
+ {
+ sscanf(buf, "%*s %n", &p);
+ cmd->p1 = strlen(buf+p);
+ ext[0].ptr = buf+p;
+ }
+ ext[0].size = cmd->p1;
valid = 1;
}
break;
case 11: /* WVAS
*/
- if (argc == 6)
+ if ((argc == 0) || (argc == 6))
{
- f = sscanf(buf, " %7s %d %d %d ",
- str, &cmd->p1, &ext[0].data, &ext[1].data);
- if (f == 4)
+ f = sscanf(buf, " %*s %d %d %d %n",
+ &cmd->p1, &ext[0].data, &ext[1].data, &p);
+ if (f == 3)
{
- ext[0].n = sizeof(unsigned);
+ ext[0].size = sizeof(unsigned);
ext[0].ptr = &ext[0].data;
- ext[1].n = sizeof(unsigned);
+ ext[1].size = sizeof(unsigned);
ext[1].ptr = &ext[1].data;
- cmd->p2 = strlen(argv[5]);
- ext[2].n = cmd->p2;
- ext[2].ptr = argv[5];
+
+ if (argc) /* pigs */
+ {
+ cmd->p2 = strlen(argv[5]);
+ ext[2].ptr = argv[5];
+ }
+ else /* pipe i/f */
+ {
+ cmd->p2 = strlen(buf+p);
+ ext[2].ptr = buf+p;
+ }
+
+ ext[2].size = cmd->p2;
valid = 1;
}
}
break;
}
- if (valid) return idx;
- else return -1;
+ if (valid) return idx; else return -1;
}
char * cmdErrStr(int error)
diff --git a/pigpio.c b/pigpio.c
index 2c37817..cde0e58 100644
--- a/pigpio.c
+++ b/pigpio.c
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to
*/
-/* pigpio version 11 */
+/* pigpio version 12 */
#include
#include
@@ -557,6 +557,9 @@ bit 0 READ_LAST_NOT_SET_ERROR
#define MAX_EMITS (PIPE_BUF / sizeof(gpioReport_t))
+#define SRX_BUF_SIZE 8192
+#define CMD_BUF_SIZE 2048
+
/* --------------------------------------------------------------- */
typedef void (*callbk_t) ();
@@ -701,16 +704,21 @@ typedef struct
typedef struct
{
- gpioRx_t * rxp;
- uint32_t baud;
- uint32_t fullBit;
- uint32_t halfBit;
- uint32_t startBitTick;
- uint32_t nextBitDiff;
- int bit;
- int byte;
- int level;
- int mode;
+ int gpio;
+ char * buf;
+ uint32_t bufSize;
+ int readPos;
+ int writePos;
+ uint32_t baud;
+ uint32_t fullBit;
+ uint32_t halfBit;
+ int timeout;
+ uint32_t startBitTick;
+ uint32_t nextBitDiff;
+ int bit;
+ int byte;
+ int level;
+ int mode;
} wfRx_t;
@@ -757,7 +765,7 @@ static wfStats_t wfStats=
0, 0, (PAGES_PER_BLOCK * CBS_PER_OPAGE)
};
-static wfRx_t wfRx[PI_MAX_USER_GPIO+1];
+static volatile wfRx_t wfRx[PI_MAX_USER_GPIO+1];
static volatile uint32_t alertBits = 0;
static volatile uint32_t monitorBits = 0;
@@ -977,7 +985,8 @@ static uint32_t myGetTick(int pos)
/* ----------------------------------------------------------------------- */
-static void myDoCommand(cmdCmd_t *cmd, gpioExtent_t *ext)
+static void myDoCommand
+ (cmdCmd_t *cmd, gpioExtent_t *iExt, gpioExtent_t *oExt)
{
int p1, p2, res, i;
uint32_t mask, tmp;
@@ -1090,7 +1099,7 @@ static void myDoCommand(cmdCmd_t *cmd, gpioExtent_t *ext)
case PI_CMD_PRG: res = gpioGetPWMrange(p1); break;
case PI_CMD_PROC:
- res = gpioStoreScript(ext[0].ptr);
+ res = gpioStoreScript(iExt[0].ptr);
break;
case PI_CMD_PROCD: res = gpioDeleteScript(p1); break;
@@ -1132,6 +1141,36 @@ static void myDoCommand(cmdCmd_t *cmd, gpioExtent_t *ext)
case PI_CMD_READ: res = gpioRead(p1); break;
+ case PI_CMD_SERVO:
+ if (gpioMask & (uint64_t)(1<bit >= 0)
{
@@ -1680,9 +1699,15 @@ static void waveRxSerial(wfRx_t * s, int level, uint32_t tick)
if (s->bit == 9)
{
- s->rxp->buf[s->rxp->writePos] = s->byte;
+ s->buf[s->writePos] = s->byte;
- if (++s->rxp->writePos >= s->rxp->bufSize) s->rxp->writePos = 0;
+ /* don't let writePos catch readPos */
+
+ newWritePos = s->writePos;
+
+ if (++newWritePos >= s->bufSize) newWritePos = 0;
+
+ if (newWritePos != s->readPos) s->writePos = newWritePos;
if (level == 0) /* true transition high->low, not a timeout */
{
@@ -1690,7 +1715,11 @@ static void waveRxSerial(wfRx_t * s, int level, uint32_t tick)
s->startBitTick = tick;
s->nextBitDiff = s->halfBit;
}
- else s->bit = -1;
+ else
+ {
+ s->bit = -1;
+ gpioSetWatchdog(s->gpio, 0);
+ }
}
}
else
@@ -1699,6 +1728,7 @@ static void waveRxSerial(wfRx_t * s, int level, uint32_t tick)
if (level == 0)
{
+ gpioSetWatchdog(s->gpio, s->timeout);
s->level = 0;
s->bit = 0;
s->startBitTick = tick;
@@ -2621,10 +2651,12 @@ static void * pthTimerTick(void *x)
static void * pthFifoThread(void *x)
{
- char inBuf[256];
- int idx, flags;
+ char buf[CMD_BUF_SIZE];
+ int idx, flags, len;
cmdCmd_t cmd;
- gpioExtent_t ext[3];
+ gpioExtent_t iExt[3];
+ gpioExtent_t oExt[3];
+ char *p;
myCreatePipe(PI_INPFIFO, 0662);
@@ -2643,12 +2675,23 @@ static void * pthFifoThread(void *x)
while (1)
{
- if (fgets(inBuf, sizeof(inBuf), inpFifo) == NULL)
+ if (fgets(buf, sizeof(buf), inpFifo) == NULL)
SOFT_ERROR((void*)PI_INIT_FAILED, "fifo fgets failed (%m)");
- if ((idx=cmdParse(inBuf, &cmd, 0, NULL, ext)) >= 0)
+ len = strlen(buf);
+
+ if (len)
{
- myDoCommand(&cmd, NULL);
+ --len;
+ buf[len] = 0; /* replace terminating */
+ }
+
+ if ((idx=cmdParse(buf, &cmd, 0, NULL, iExt)) >= 0)
+ {
+ oExt[0].ptr = buf;
+ oExt[0].size = CMD_BUF_SIZE-1;
+
+ myDoCommand(&cmd, iExt, oExt);
switch (cmdInfo[idx].rv)
{
@@ -2675,6 +2718,17 @@ static void * pthFifoThread(void *x)
case 5:
fprintf(outFifo, cmdUsage);
break;
+
+ case 6:
+ if (cmd.res < 0) fprintf(outFifo, "%d\n", cmd.res);
+ else if (cmd.res > 0)
+ {
+ p = oExt[0].ptr;
+ p[cmd.res] = 0;
+ fprintf(outFifo, "%s", (char *)oExt[0].ptr);
+ }
+ break;
+
}
}
@@ -2694,8 +2748,13 @@ static void *pthSocketThreadHandler(void *fdC)
cmdCmd_t cmd;
unsigned bytes;
char *memPtr;
- gpioExtent_t ext[3];
+ gpioExtent_t iExt[3];
+ gpioExtent_t oExt[3];
unsigned tmp;
+ char buf[CMD_BUF_SIZE];
+
+ oExt[0].size = CMD_BUF_SIZE-1;
+ oExt[0].ptr = buf;
free(fdC);
@@ -2719,13 +2778,14 @@ static void *pthSocketThreadHandler(void *fdC)
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);
+ iExt[0].size = bytes;
+ iExt[0].ptr = memPtr;
+ myDoCommand(&cmd, iExt, oExt);
free(memPtr);
}
else
@@ -2756,14 +2816,14 @@ static void *pthSocketThreadHandler(void *fdC)
{
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);
+ iExt[0].size = sizeof(unsigned);
+ iExt[0].ptr = memPtr;
+ iExt[1].size = sizeof(unsigned);
+ iExt[1].ptr = memPtr + sizeof(unsigned);
+ iExt[2].size = cmd.p2;
+ iExt[2].ptr = memPtr + sizeof(unsigned) + sizeof(unsigned);
memPtr[bytes] = 0; /* may be duplicate terminator */
- myDoCommand(&cmd, ext);
+ myDoCommand(&cmd, iExt, oExt);
free(memPtr);
}
else
@@ -2787,24 +2847,24 @@ static void *pthSocketThreadHandler(void *fdC)
bytes = cmd.p1;
memPtr = malloc(bytes+1); /* add 1 for a nul terminator */
+
if (memPtr)
{
- if (recv(sock, memPtr, bytes, MSG_WAITALL) == bytes)
+ if (bytes) /* script appended */
{
- ext[0].n = bytes;
- ext[0].ptr = memPtr;
- memPtr[bytes] = 0; /* may be duplicate terminator */
- myDoCommand(&cmd, ext);
- free(memPtr);
- }
- else
- {
- free(memPtr);
- break;
+ if (recv(sock, memPtr, bytes, MSG_WAITALL) != bytes)
+ {
+ free(memPtr);
+ break;
+ }
}
+ iExt[0].size = bytes;
+ iExt[0].ptr = memPtr;
+ memPtr[bytes] = 0; /* may be duplicate terminator */
+ myDoCommand(&cmd, iExt, oExt);
+ free(memPtr);
}
else break;
-
}
else
{
@@ -2817,8 +2877,8 @@ static void *pthSocketThreadHandler(void *fdC)
## extension ##
unsigned level
*/
- ext[0].n = 4;
- ext[0].ptr = &tmp;
+ iExt[0].size = 4;
+ iExt[0].ptr = &tmp;
if (recv(sock, &tmp, sizeof(unsigned), MSG_WAITALL) !=
sizeof(unsigned))
@@ -2831,11 +2891,26 @@ static void *pthSocketThreadHandler(void *fdC)
default:
break;
}
- myDoCommand(&cmd, ext);
+ myDoCommand(&cmd, iExt, oExt);
}
write(sock, &cmd, sizeof(cmdCmd_t));
+ switch (cmd.cmd)
+ {
+ case PI_CMD_SLR: /* extension */
+
+ if (cmd.res > 0)
+ {
+ write(sock, oExt[0].ptr, cmd.res);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
}
else break;
}
@@ -4347,6 +4422,9 @@ int gpioWaveAddSerial(unsigned gpio,
DBG(DBG_USER, "gpio=%d baud=%d offset=%d numChar=%d str=%s",
gpio, baud, offset, numChar, str);
+ DBG(DBG_USER, "l=%d s=%X e=%X",
+ strlen(str), str[0], str[strlen(str)-1]);
+
CHECK_INITED;
if (gpio > PI_MAX_USER_GPIO)
@@ -4439,13 +4517,11 @@ int gpioWaveAddSerial(unsigned gpio,
/*-------------------------------------------------------------------------*/
-int gpioWaveSerialReadStart(unsigned gpio,
- unsigned baud,
- gpioRx_t *rxp)
+int gpioSerialReadOpen(unsigned gpio, unsigned baud)
{
- int bitTime, timeoutMs;
+ int bitTime, timeout;
- DBG(DBG_USER, "gpio=%d baud=%d rxp*=%08X", gpio, baud, (uint32_t)rxp);
+ DBG(DBG_USER, "gpio=%d baud=%d", gpio, baud);
CHECK_INITED;
@@ -4456,37 +4532,75 @@ int gpioWaveSerialReadStart(unsigned gpio,
SOFT_ERROR(PI_BAD_WAVE_BAUD,
"gpio %d, bad baud rate (%d)", gpio, baud);
- if (rxp == NULL)
- SOFT_ERROR(PI_BAD_SERIAL_STRUC, "Null structure pointer");
-
- if (rxp->buf == NULL)
- SOFT_ERROR(PI_BAD_SERIAL_BUF, "Null buffer pointer");
+ if (wfRx[gpio].mode != PI_WFRX_NONE)
+ SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used", gpio);
bitTime = MILLION / baud;
- timeoutMs = ((12 * bitTime)+1000)/1000;
+ timeout = (10 * bitTime)/1000;
+ if (timeout < 1) timeout = 1;
+ wfRx[gpio].gpio = gpio;
+ wfRx[gpio].buf = malloc(SRX_BUF_SIZE);
+ wfRx[gpio].bufSize = SRX_BUF_SIZE;
wfRx[gpio].mode = PI_WFRX_SERIAL;
wfRx[gpio].baud = baud;
- wfRx[gpio].rxp = rxp;
- wfRx[gpio].baud = baud;
+ wfRx[gpio].timeout = timeout;
wfRx[gpio].fullBit = bitTime;
wfRx[gpio].halfBit = bitTime/2;
- wfRx[gpio].rxp->readPos = 0;
- wfRx[gpio].rxp->writePos = 0;
+ wfRx[gpio].readPos = 0;
+ wfRx[gpio].writePos = 0;
wfRx[gpio].bit = -1;
- gpioSetWatchdog(gpio, timeoutMs); /* get a nudge if no change */
-
gpioSetAlertFunc(gpio, waveRxBit);
return 0;
}
+/*-------------------------------------------------------------------------*/
+
+int gpioSerialRead(unsigned gpio, void *buf, size_t bufSize)
+{
+ unsigned bytes=0, wpos;
+ volatile wfRx_t *p;
+
+ DBG(DBG_USER, "gpio=%d buf=%08X bufSize=%d", gpio, (int)buf, bufSize);
+
+ CHECK_INITED;
+
+ if (gpio > PI_MAX_USER_GPIO)
+ SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
+
+ if (bufSize == 0)
+ SOFT_ERROR(PI_BAD_SERIAL_COUNT, "buffer size can't be zero");
+
+ if (wfRx[gpio].mode != PI_WFRX_SERIAL)
+ SOFT_ERROR(PI_NOT_SERIAL_GPIO, "no serial read on gpio (%d)", gpio);
+
+ p = &wfRx[gpio];
+
+ if (p->readPos != p->writePos)
+ {
+ wpos = p->writePos;
+
+ if (wpos > p->readPos) bytes = wpos - p->readPos;
+ else bytes = p->bufSize - p->readPos;
+
+ if (bytes > bufSize) bytes = bufSize;
+
+ memcpy(buf, p->buf+p->readPos, bytes);
+
+ p->readPos += bytes;
+
+ if (p->readPos >= p->bufSize) p->readPos = 0;
+ }
+ return bytes;
+}
+
/*-------------------------------------------------------------------------*/
-int gpioWaveSerialReadStop(unsigned gpio)
+int gpioSerialReadClose(unsigned gpio)
{
DBG(DBG_USER, "gpio=%d", gpio);
@@ -4505,6 +4619,8 @@ int gpioWaveSerialReadStop(unsigned gpio)
case PI_WFRX_SERIAL:
+ free(wfRx[gpio].buf);
+
gpioSetWatchdog(gpio, 0); /* switch off timeouts */
gpioSetAlertFunc(gpio, NULL); /* cancel alert */
@@ -5067,6 +5183,8 @@ void gpioStopThread(pthread_t *pth)
int gpioStoreScript(char *script)
{
DBG(DBG_USER, "script=%s", script);
+ DBG(DBG_USER, "l=%d s=%X e=%X",
+ strlen(script), script[0], script[strlen(script)-1]);
CHECK_INITED;
diff --git a/pigpio.h b/pigpio.h
index cf91696..bf5fa89 100644
--- a/pigpio.h
+++ b/pigpio.h
@@ -26,7 +26,7 @@ For more information, please refer to
*/
/*
-This version is for pigpio version 11
+This version is for pigpio version 12
*/
#ifndef PIGPIO_H
@@ -86,7 +86,7 @@ This version is for pigpio version 11
#include
#include
-#define PIGPIO_VERSION 11
+#define PIGPIO_VERSION 12
/*-------------------------------------------------------------------------*/
@@ -133,8 +133,9 @@ gpioWaveTxStart Transmits the waveform.
gpioWaveTxBusy Checks to see if the waveform has ended.
gpioWaveTxStop Aborts the current waveform.
-gpioWaveSerialReadStart Reads serial data from a user gpio.
-gpioWaveSerialReadStop Stops reading serial data from a user gpio.
+gpioSerialReadOpen Opens a gpio for reading serial data.
+gpioSerialRead Reads serial data from a gpio.
+gpioSerialReadClose Closes a gpio for reading serial data.
gpioWaveGetMicros Length in microseconds of the current waveform.
gpioWaveGetHighMicros Length of longest waveform so far.
@@ -226,7 +227,7 @@ typedef struct
typedef struct
{
- size_t n;
+ size_t size;
void *ptr;
int data;
} gpioExtent_t;
@@ -252,14 +253,6 @@ typedef struct
uint32_t usDelay;
} gpioPulse_t;
-typedef struct
-{
- char * buf;
- uint32_t bufSize;
- int readPos;
- int writePos;
-} gpioRx_t;
-
typedef void (*gpioAlertFunc_t) (int gpio,
int level,
uint32_t tick);
@@ -974,76 +967,38 @@ int gpioWaveTxStop(void);
/*-------------------------------------------------------------------------*/
-int gpioWaveSerialReadStart(unsigned user_gpio,
- unsigned baud,
- gpioRx_t * rxp);
+int gpioSerialReadOpen(unsigned user_gpio, unsigned baud);
/*-------------------------------------------------------------------------*/
-/* This function starts the reception of serial data with the
- specified baud rate on a gpio.
+/* This function opens a gpio for reading serial data.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD,
- PI_BAD_SERIAL_STRUC, or PI_BAD_SERIAL_BUF.
+ or PI_GPIO_IN_USE.
- NOTES:
-
- typedef struct
- {
- char * buf;
- uint32_t bufSize;
- int readPos;
- int writePos;
- } gpioRx_t;
-
- The serial data is returned in a cyclic buffer which MUST be allocated
- by the caller. The caller specifies the location and size of the
- buffer in buf and bufSize.
+ The serial data is returned in a cyclic buffer and is read using
+ gpioSerialRead().
It is the caller's responsibility to read data from the cyclic buffer
- in a timely fashion. Data is available when readPos is not equal to
- writePos.
-
- EXAMPLE:
-
- #define BUFSIZE 1000
-
- char buf[BUFSIZE];
- int bytes, wpos;
- FILE * outFile;
-
- gpioRx_t rx;
-
- ...
-
- rx.buf = buf;
- rx.bufSize = sizeof(buf);
-
- if (gpioWaveSerialReadStart(4, 38400, &rx) == 0)
- {
- ...
-
- while (rx.readPos != rx.writePos)
- {
- wpos = rx.writePos;
-
- if (wpos > rx.readPos) bytes = wpos - rx.readPos;
- else bytes = rx.bufSize - rx.readPos;
-
- fwrite(rx.buf+rx.readPos, 1, bytes, outFile);
-
- rx.readPos += bytes;
-
- if (rx.readPos >= rx.bufSize) rx.readPos = 0;
- }
- ...
- }
+ in a timely fashion.
*/
/*-------------------------------------------------------------------------*/
-int gpioWaveSerialReadStop(unsigned user_gpio);
+int gpioSerialRead(unsigned user_gpio, void *buf, size_t bufSize);
/*-------------------------------------------------------------------------*/
-/* This function stops reading serial data from a gpio.
+/* This function copies up to bufSize bytes of data read from the
+ serial cyclic buffer to the buffer starting at buf.
+
+ Returns the number of bytes copied if OK, otherwise PI_BAD_USER_GPIO
+ or PI_NOT_SERIAL_GPIO.
+*/
+
+
+
+/*-------------------------------------------------------------------------*/
+int gpioSerialReadClose(unsigned user_gpio);
+/*-------------------------------------------------------------------------*/
+/* This function closes a gpio for reading serial data.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SERIAL_GPIO.
*/
@@ -1901,6 +1856,9 @@ void gpioWaveDump(void);
#define PI_CMD_PROCD 39
#define PI_CMD_PROCR 40
#define PI_CMD_PROCS 41
+#define PI_CMD_SLRO 42
+#define PI_CMD_SLR 43
+#define PI_CMD_SLRC 44
/*
The following command only works on the socket interface.
@@ -1970,6 +1928,8 @@ after this command is issued.
#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 */
+#define PI_GPIO_IN_USE -50 /* gpio already in use */
+#define PI_BAD_SERIAL_COUNT -51 /* must read at least a byte at a time */
/*-------------------------------------------------------------------------*/
diff --git a/pigpio.py b/pigpio.py
index 0b40af8..dd74105 100644
--- a/pigpio.py
+++ b/pigpio.py
@@ -76,7 +76,7 @@ import threading
import os
import atexit
-VERSION = "1.2"
+VERSION = "1.3"
# gpio levels
@@ -157,6 +157,9 @@ _PI_CMD_PROC= 38
_PI_CMD_PROCD=39
_PI_CMD_PROCR=40
_PI_CMD_PROCS=41
+_PI_CMD_SLRO= 42
+_PI_CMD_SLR= 43
+_PI_CMD_SLRC= 44
_PI_CMD_NOIB= 99
@@ -202,7 +205,7 @@ _PI_BAD_CFG_INTERNAL=-34
PI_BAD_WAVE_BAUD =-35
PI_TOO_MANY_PULSES =-36
PI_TOO_MANY_CHARS =-37
-_PI_NOT_SERIAL_GPIO =-38
+PI_NOT_SERIAL_GPIO =-38
_PI_BAD_SERIAL_STRUC=-39
_PI_BAD_SERIAL_BUF =-40
PI_NOT_PERMITTED =-41
@@ -214,6 +217,7 @@ PI_BAD_PULSELEN =-46
PI_BAD_SCRIPT =-47
PI_BAD_SCRIPT_ID =-48
PI_BAD_SER_OFFSET =-49
+PI_GPIO_IN_USE =-50
# pigpio error text
@@ -252,10 +256,10 @@ _errors=[
[_PI_INITIALISED , "function called after gpioInitialise"],
[_PI_BAD_WAVE_MODE , "waveform mode not 0-1"],
[_PI_BAD_CFG_INTERNAL , "bad parameter in gpioCfgInternals call"],
- [PI_BAD_WAVE_BAUD , "baud rate not 100-250000"],
- [PI_TOO_MANY_PULSES , "waveform has too many pulses"],
- [PI_TOO_MANY_CHARS , "waveform has too many chars"],
- [_PI_NOT_SERIAL_GPIO , "no serial read in progress on gpio"],
+ [PI_BAD_WAVE_BAUD , "baud rate not 100-250000"],
+ [PI_TOO_MANY_PULSES , "waveform has too many pulses"],
+ [PI_TOO_MANY_CHARS , "waveform has too many chars"],
+ [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"],
[PI_BAD_WVSC_COMMND , "bad WVSC subcommand"],
@@ -265,6 +269,7 @@ _errors=[
[PI_BAD_SCRIPT , "invalid script"],
[PI_BAD_SCRIPT_ID , "unknown script id"],
[PI_BAD_SER_OFFSET , "add serial data offset > 30 minute"],
+ [PI_GPIO_IN_USE , "gpio already in use"],
]
_control = None
@@ -1701,6 +1706,46 @@ def delete_script(script_id):
"""
return _u2i(_pigpio_command(_control, _PI_CMD_PROCD, script_id, 0))
+def serial_read_open(user_gpio, baud):
+ """
+ This function opens a gpio for reading serial data.
+
+ Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD,
+ or PI_GPIO_IN_USE.
+
+ The serial data is held in a cyclic buffer and is read using
+ gpioSerialRead().
+
+ It is the caller's responsibility to read data from the cyclic buffer
+ in a timely fashion.
+ """
+ return _u2i(_pigpio_command(_control, _PI_CMD_SLRO, user_gpio, baud))
+
+def serial_read(user_gpio):
+ """
+ This function returns data from the serial cyclic buffer.
+
+ It returns a tuple of status and string. The status will be the
+ length, possibly 0, of the returned string if OK. Otherwise a
+ negative error code will be returned in which case the string
+ will be null.
+ """
+ bytes = _u2i(_pigpio_command(_control, _PI_CMD_SLR, user_gpio, 10000))
+ if bytes > 0:
+ buf = ""
+ while len(buf) < bytes: buf += _control.recv(bytes-len(buf))
+ return bytes, buf
+ return bytes, ""
+
+
+def serial_read_close(user_gpio):
+ """
+ This function closes a gpio for reading serial data.
+
+ Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SERIAL_GPIO.
+ """
+ return _u2i(_pigpio_command(_control, _PI_CMD_SLRC, user_gpio, 0))
+
class callback:
"""A class to provide gpio level change callbacks."""
diff --git a/pigpiod_if.c b/pigpiod_if.c
index e6884fd..4960150 100644
--- a/pigpiod_if.c
+++ b/pigpiod_if.c
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to
*/
-/* PIGPIOD_IF_VERSION 2 */
+/* PIGPIOD_IF_VERSION 3 */
#include
#include
@@ -59,6 +59,7 @@ typedef void (*CBF_t) ();
struct callback_s
{
+
int id;
int gpio;
int edge;
@@ -120,7 +121,7 @@ static int pigpio_command_ext
for (i=0; i 0)
+ {
+ /* get the data */
+ recv(gPigCommand, buf, bytes, MSG_WAITALL);
+ }
+ return bytes;
+}
+
+int serial_read_close(unsigned gpio)
+ {return pigpio_command(gPigCommand, PI_CMD_SLRC, gpio, 0);}
+
+int callback(unsigned gpio, unsigned edge, CBFunc_t f)
{return intCallback(gpio, edge, f, 0, 0);}
-int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user)
+int callback_ex(unsigned gpio, unsigned edge, CBFuncEx_t f, void *user)
{return intCallback(gpio, edge, f, user, 1);}
-int callback_cancel(int id)
+int callback_cancel(unsigned id)
{
callback_t *p;
@@ -766,7 +787,7 @@ int callback_cancel(int id)
return pigif_callback_not_found;
}
-int wait_for_edge(int gpio, int edge, double timeout)
+int wait_for_edge(unsigned gpio, unsigned edge, double timeout)
{
int triggered = 0;
int id;
diff --git a/pigpiod_if.h b/pigpiod_if.h
index 6c009e2..c8e8fc5 100644
--- a/pigpiod_if.h
+++ b/pigpiod_if.h
@@ -30,7 +30,7 @@ For more information, please refer to
#include "pigpio.h"
-#define PIGPIOD_IF_VERSION 2
+#define PIGPIOD_IF_VERSION 3
typedef enum
{
@@ -45,12 +45,13 @@ typedef enum
pigif_bad_callback = -2008,
pigif_notify_failed = -2009,
pigif_callback_not_found = -2010,
-} piscopeError_t;
+} pigifError_t;
-typedef void (*CBFunc_t) (int gpio, int level, uint32_t tick);
+typedef void (*CBFunc_t) (unsigned gpio, unsigned level, uint32_t tick);
-typedef void (*CBFuncEx_t)(int gpio, int level, uint32_t tick, void * user);
+typedef void (*CBFuncEx_t)
+ (unsigned gpio, unsigned level, uint32_t tick, void * user);
typedef struct callback_s callback_t;
@@ -110,7 +111,7 @@ void pigpio_stop(void);
resources used by the library.
*/
-int set_mode(int gpio, int mode);
+int set_mode(unsigned gpio, unsigned mode);
/* Set the gpio mode.
gpio: 0-53.
@@ -120,7 +121,7 @@ int set_mode(int gpio, int mode);
or PI_NOT_PERMITTED.
*/
-int get_mode(int gpio);
+int get_mode(unsigned gpio);
/* Get the gpio mode.
Returns the gpio mode if OK, otherwise PI_BAD_GPIO.
@@ -128,7 +129,7 @@ int get_mode(int gpio);
gpio: 0-53.
*/
-int set_pull_up_down(int gpio, int pud);
+int set_pull_up_down(unsigned gpio, unsigned pud);
/* Set or clear the gpio pull-up/down resistor.
Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_PUD,
@@ -138,7 +139,7 @@ int set_pull_up_down(int gpio, int pud);
pud: PUD_UP, PUD_DOWN, PUD_OFF.
*/
-int read_gpio(int gpio);
+int read_gpio(unsigned gpio);
/* Read the gpio level.
Returns the gpio level if OK, otherwise PI_BAD_GPIO.
@@ -146,7 +147,7 @@ int read_gpio(int gpio);
gpio:0-53.
*/
-int write_gpio(int gpio, int level);
+int write_gpio(unsigned gpio, unsigned level);
/*
Write the gpio level.
@@ -161,7 +162,7 @@ int write_gpio(int gpio, int level);
If PWM or servo pulses are active on the gpio they are switched off.
*/
-int set_PWM_dutycycle(int user_gpio, int dutycycle);
+int set_PWM_dutycycle(unsigned user_gpio, unsigned dutycycle);
/* Start (non-zero dutycycle) or stop (0) PWM pulses on the gpio.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_DUTYCYCLE,
@@ -175,7 +176,7 @@ int set_PWM_dutycycle(int user_gpio, int dutycycle);
The set_PWM_range() function can change the default range of 255.
*/
-int set_PWM_range(int user_gpio, int range_);
+int set_PWM_range(unsigned user_gpio, unsigned range_);
/* Set the range of PWM values to be used on the gpio.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_DUTYRANGE,
@@ -200,7 +201,7 @@ int set_PWM_range(int user_gpio, int range_);
(dutycycle * real range) / range.
*/
-int get_PWM_range(int user_gpio);
+int get_PWM_range(unsigned user_gpio);
/* Get the range of PWM values being used on the gpio.
Returns the dutycycle range used for the gpio if OK,
@@ -209,7 +210,7 @@ int get_PWM_range(int user_gpio);
user_gpio: 0-31.
*/
-int get_PWM_real_range(int user_gpio);
+int get_PWM_real_range(unsigned user_gpio);
/* Get the real underlying range of PWM values being used on the gpio.
Returns the real range used for the gpio if OK,
@@ -218,7 +219,7 @@ int get_PWM_real_range(int user_gpio);
user_gpio: 0-31.
*/
-int set_PWM_frequency(int user_gpio, int frequency);
+int set_PWM_frequency(unsigned user_gpio, unsigned frequency);
/*
Set the frequency (in Hz) of the PWM to be used on the gpio.
@@ -257,7 +258,7 @@ int set_PWM_frequency(int user_gpio, int frequency);
125, 100, 80, 50, 40, 25, 20, 10, 5
*/
-int get_PWM_frequency(int user_gpio);
+int get_PWM_frequency(unsigned user_gpio);
/*
Get the frequency of PWM being used on the gpio.
@@ -267,7 +268,7 @@ int get_PWM_frequency(int user_gpio);
user_gpio: 0-31.
*/
-int set_servo_pulsewidth(int user_gpio, int pulsewidth);
+int set_servo_pulsewidth(unsigned user_gpio, unsigned pulsewidth);
/*
Start (500-2500) or stop (0) servo pulses on the gpio.
@@ -330,7 +331,7 @@ int notify_open(void);
read from /dev/pigpio15.
*/
-int notify_begin(int handle, uint32_t bits);
+int notify_begin(unsigned handle, uint32_t bits);
/*
Start notifications on a previously opened handle.
@@ -352,7 +353,7 @@ int notify_begin(int handle, uint32_t bits);
I (32 bit) level
*/
-int notify_pause(int handle);
+int notify_pause(unsigned handle);
/*
Pause notifications on a previously opened handle.
@@ -364,7 +365,7 @@ int notify_pause(int handle);
notify_begin() is called again.
*/
-int notify_close(int handle);
+int notify_close(unsigned handle);
/*
Stop notifications on a previously opened handle and
release the handle for reuse.
@@ -374,7 +375,7 @@ int notify_close(int handle);
handle: 0-31 (as returned by notify_open())
*/
-int set_watchdog(int user_gpio, int timeout);
+int set_watchdog(unsigned user_gpio, unsigned timeout);
/*
Sets a watchdog for a gpio.
@@ -658,25 +659,52 @@ int store_script(char *script);
otherwise PI_BAD_SCRIPT.
*/
-int run_script(int script_id);
+int run_script(unsigned 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);
+int stop_script(unsigned 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);
+int delete_script(unsigned 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 serial_read_open(unsigned user_gpio, unsigned baud);
+/* This function opens a gpio for reading serial data.
+
+ Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD,
+ or PI_GPIO_IN_USE.
+
+ The serial data is returned in a cyclic buffer and is read using
+ gpioSerialRead().
+
+ It is the caller's responsibility to read data from the cyclic buffer
+ in a timely fashion.
+*/
+
+int serial_read(unsigned user_gpio, void *buf, size_t bufSize);
+/* This function copies up to bufSize bytes of data read from the
+ serial cyclic buffer to the buffer starting at buf.
+
+ Returns the number of bytes copied if OK, otherwise PI_BAD_USER_GPIO
+ or PI_NOT_SERIAL_GPIO.
+*/
+
+int serial_read_close(unsigned user_gpio);
+/* This function closes a gpio for reading serial data.
+
+ Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SERIAL_GPIO.
+*/
+
+int callback(unsigned gpio, unsigned edge, CBFunc_t f);
/*
This function initialises a new callback.
@@ -687,7 +715,7 @@ int callback(int gpio, int edge, CBFunc_t f);
gpio has the identified edge.
*/
-int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user);
+int callback_ex(unsigned gpio, unsigned edge, CBFuncEx_t f, void *user);
/*
This function initialises a new callback.
@@ -698,14 +726,14 @@ int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user);
the gpio has the identified edge.
*/
-int callback_cancel(int id);
+int callback_cancel(unsigned 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(unsigned gpio, unsigned edge, double timeout);
/*
This function waits for edge on the gpio for up to timeout
seconds.
diff --git a/pigs.c b/pigs.c
index 4cd84c2..4043c70 100644
--- a/pigs.c
+++ b/pigs.c
@@ -26,7 +26,7 @@ For more information, please refer to
*/
/*
-This version is for pigpio version 11+
+This version is for pigpio version 12+
*/
#include
@@ -153,10 +153,11 @@ int main(int argc , char *argv[])
for (i=0; i 0)
+ {
+ recv(sock, &buf, r, MSG_WAITALL);
+ buf[r] = 0;
+ printf("%s", buf);
+ }
+ break;
}
}
else fatal("recv failed, %m");
diff --git a/setup.py b/setup.py
index 270786b..3a8ea36 100644
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
from distutils.core import setup
setup(name='pigpio',
- version='1.2',
+ version='1.3',
author='joan',
author_email='joan@abyz.me.uk',
maintainer='joan',