TEST (optional)
+*** WARNING ************************************************
+* *
+* All the tests make extensive use of gpio 4 (pin P1-7). *
+* Ensure that either nothing or just a LED is connected to *
+* gpio 4 before running any of the tests. *
+************************************************************
+
To test the library do
sudo ./x_pigpio
-To text the pigpio daemon do
+To test the pigpio daemon do
sudo pigpiod
with the pigpio library.
pigs.c, pigpio.py, x_pigpiod_if.c, x_pigpio.py, x_pigs, and x_pipe
-show examples of interfacing with the pigpiod daemon.
+show examples of interfacing with the pigpio daemon.
DAEMON
*/
/*
-This version is for pigpio version 13+
+This version is for pigpio version 14+
*/
#include <stdio.h>
#include "pigpio.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
-6 %s <0 ERR
-*/
-
-/* 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 PROC %s
-11 WVAS %d %d %d %s
-12 PROCR %d [%d]*10
-13 WVAG %d %d %d [%d %d %d]*160
-
-
-20 cmd m(0-150)
-21 cmd v
-22 cmd L
-23 cmd
-24 cmd m1(0-150) m2(0-150)
-25 cmd p(0-9)
-*/
-
cmdInfo_t cmdInfo[]=
{
/* num str vfyt retv */
- {PI_CMD_BC1, "BC1", 7, 1},
- {PI_CMD_BC2, "BC2", 7, 1},
- {PI_CMD_BR1, "BR1", 1, 3},
- {PI_CMD_BR2, "BR2", 1, 3},
- {PI_CMD_BS1, "BS1", 7, 1},
- {PI_CMD_BS2, "BS2", 7, 1},
- {PI_CMD_HELP, "H", 6, 5},
- {PI_CMD_HELP, "HELP", 6, 5},
- {PI_CMD_HWVER, "HWVER", 1, 4},
- {PI_CMD_MICRO, "MICRO", 21, 0},
- {PI_CMD_MILLI, "MILLI", 21, 0},
- {PI_CMD_MODEG, "MG" , 2, 2},
- {PI_CMD_MODEG, "MODEG", 2, 2},
- {PI_CMD_MODES, "M", 8, 0},
- {PI_CMD_MODES, "MODES", 8, 0},
- {PI_CMD_NB, "NB", 4, 0},
- {PI_CMD_NC, "NC", 2, 0},
- {PI_CMD_NO, "NO", 1, 2},
- {PI_CMD_NP, "NP", 2, 0},
- {PI_CMD_PFG, "PFG", 2, 2},
- {PI_CMD_PFS, "PFS", 3, 2},
- {PI_CMD_PIGPV, "PIGPV", 1, 4},
- {PI_CMD_PRG, "PRG", 2, 2},
- {PI_CMD_PROC, "PROC", 10, 2},
- {PI_CMD_PROCD, "PROCD", 2, 2},
- {PI_CMD_PROCP, "PROCP", 2, 7},
- {PI_CMD_PROCR, "PROCR",12, 2},
- {PI_CMD_PROCS, "PROCS", 2, 2},
- {PI_CMD_PRRG, "PRRG", 2, 2},
- {PI_CMD_PRS, "PRS", 3, 2},
- {PI_CMD_PUD, "PUD", 9, 0},
- {PI_CMD_PWM, "P", 3, 0},
- {PI_CMD_PWM, "PWM", 3, 0},
- {PI_CMD_READ, "R", 2, 2},
- {PI_CMD_READ, "READ", 2, 2},
- {PI_CMD_SERVO, "S", 3, 0},
- {PI_CMD_SERVO, "SERVO", 3, 0},
- {PI_CMD_SLR, "SLR", 3, 6},
- {PI_CMD_SLRC, "SLRC", 2, 2},
- {PI_CMD_SLRO, "SLRO", 3, 2},
- {PI_CMD_TICK, "T", 1, 4},
- {PI_CMD_TICK, "TICK", 1, 4},
- {PI_CMD_TRIG, "TRIG", 5, 0},
- {PI_CMD_WDOG, "WDOG", 3, 0},
- {PI_CMD_WRITE, "W", 3, 0},
- {PI_CMD_WRITE, "WRITE", 3, 0},
- {PI_CMD_WVAG, "WVAG", 13, 2},
- {PI_CMD_WVAS, "WVAS", 11, 2},
- {PI_CMD_WVBSY, "WVBSY", 1, 2},
- {PI_CMD_WVCLR, "WVCLR", 1, 2},
- {PI_CMD_WVGO, "WVGO" , 1, 2},
- {PI_CMD_WVGOR, "WVGOR", 1, 2},
- {PI_CMD_WVHLT, "WVHLT", 1, 2},
- {PI_CMD_WVSC, "WVSC", 2, 2},
- {PI_CMD_WVSM, "WVSM", 2, 2},
- {PI_CMD_WVSP, "WVSP", 2, 2},
-
- {PI_CMD_ADDI , "ADDI" , 21, 0},
- {PI_CMD_ADDV , "ADDV" , 20, 0},
- {PI_CMD_ANDI , "ANDI" , 21, 0},
- {PI_CMD_ANDV , "ANDV" , 20, 0},
- {PI_CMD_CALL , "CALL" , 22, 0},
- {PI_CMD_CMPI , "CMPI" , 21, 0},
- {PI_CMD_CMPV , "CMPV" , 20, 0},
- {PI_CMD_DCRA , "DCRA" , 23, 0},
- {PI_CMD_DCRV , "DCRV" , 20, 0},
- {PI_CMD_HALT , "HALT" , 23, 0},
- {PI_CMD_INRA , "INRA" , 23, 0},
- {PI_CMD_INRV , "INRV" , 20, 0},
- {PI_CMD_JM , "JM" , 22, 0},
- {PI_CMD_JMP , "JMP" , 22, 0},
- {PI_CMD_JNZ , "JNZ" , 22, 0},
- {PI_CMD_JP , "JP" , 22, 0},
- {PI_CMD_JZ , "JZ" , 22, 0},
- {PI_CMD_LABEL, "LABEL", 22, 0},
- {PI_CMD_LDAI , "LDAI" , 21, 0},
- {PI_CMD_LDAP , "LDAP" , 25, 0},
- {PI_CMD_LDAV , "LDAV" , 20, 0},
- {PI_CMD_LDPA , "LDPA" , 25, 0},
- {PI_CMD_LDVA , "LDVA" , 20, 0},
- {PI_CMD_LDVI , "LDVI" , 28, 0},
- {PI_CMD_LDVV , "LDVV" , 24, 0},
- {PI_CMD_ORI , "ORI" , 21, 0},
- {PI_CMD_ORV , "ORV" , 20, 0},
- {PI_CMD_POPA , "POPA" , 23, 0},
- {PI_CMD_POPV , "POPV" , 20, 0},
- {PI_CMD_PUSHA, "PUSHA", 23, 0},
- {PI_CMD_PUSHV, "PUSHV", 20, 0},
- {PI_CMD_RET , "RET" , 23, 0},
- {PI_CMD_RAL , "RAL" , 21, 0},
- {PI_CMD_RAR , "RAR" , 21, 0},
- {PI_CMD_SUBI , "SUBI" , 21, 0},
- {PI_CMD_SUBV , "SUBV" , 20, 0},
- {PI_CMD_SWAPA, "SWAPA", 20, 0},
- {PI_CMD_SWAPV, "SWAPV", 24, 0},
- {PI_CMD_SYS , "SYS" , 27, 0},
- {PI_CMD_WAITI, "WAITI", 21, 0},
- {PI_CMD_WAITV, "WAITV", 20, 0},
- {PI_CMD_XORI , "XORI" , 21, 0},
- {PI_CMD_XORV , "XORV" , 20, 0},
+ {PI_CMD_BC1, "BC1", 111, 1},
+ {PI_CMD_BC2, "BC2", 111, 1},
+ {PI_CMD_BR1, "BR1", 101, 3},
+ {PI_CMD_BR2, "BR2", 101, 3},
+ {PI_CMD_BS1, "BS1", 111, 1},
+ {PI_CMD_BS2, "BS2", 111, 1},
+ {PI_CMD_HELP, "H", 101, 5},
+ {PI_CMD_HELP, "HELP", 101, 5},
+ {PI_CMD_HWVER, "HWVER", 101, 4},
+ {PI_CMD_MICS, "MICS", 112, 0},
+ {PI_CMD_MILS, "MILS", 112, 0},
+ {PI_CMD_MODEG, "MG" , 112, 2},
+ {PI_CMD_MODEG, "MODEG", 112, 2},
+ {PI_CMD_MODES, "M", 125, 0},
+ {PI_CMD_MODES, "MODES", 125, 0},
+ {PI_CMD_NB, "NB", 122, 0},
+ {PI_CMD_NC, "NC", 112, 0},
+ {PI_CMD_NO, "NO", 101, 2},
+ {PI_CMD_NP, "NP", 112, 0},
+ {PI_CMD_PARSE, "PARSE", 115, 2},
+ {PI_CMD_PFG, "PFG", 112, 2},
+ {PI_CMD_PFS, "PFS", 121, 2},
+ {PI_CMD_PIGPV, "PIGPV", 101, 4},
+ {PI_CMD_PRG, "PRG", 112, 2},
+ {PI_CMD_PROC, "PROC", 115, 2},
+ {PI_CMD_PROCD, "PROCD", 112, 2},
+ {PI_CMD_PROCP, "PROCP", 112, 7},
+ {PI_CMD_PROCR, "PROCR", 191, 2},
+ {PI_CMD_PROCS, "PROCS", 112, 2},
+ {PI_CMD_PRRG, "PRRG", 112, 2},
+ {PI_CMD_PRS, "PRS", 121, 2},
+ {PI_CMD_PUD, "PUD", 126, 0},
+ {PI_CMD_PWM, "P", 121, 0},
+ {PI_CMD_PWM, "PWM", 121, 0},
+ {PI_CMD_READ, "R", 112, 2},
+ {PI_CMD_READ, "READ", 112, 2},
+ {PI_CMD_SERVO, "S", 121, 0},
+ {PI_CMD_SERVO, "SERVO", 121, 0},
+ {PI_CMD_SLR, "SLR", 121, 6},
+ {PI_CMD_SLRC, "SLRC", 112, 2},
+ {PI_CMD_SLRO, "SLRO", 121, 2},
+ {PI_CMD_TICK, "T", 101, 4},
+ {PI_CMD_TICK, "TICK", 101, 4},
+ {PI_CMD_TRIG, "TRIG", 131, 0},
+ {PI_CMD_WDOG, "WDOG", 121, 0},
+ {PI_CMD_WRITE, "W", 121, 0},
+ {PI_CMD_WRITE, "WRITE", 121, 0},
+ {PI_CMD_WVAG, "WVAG", 192, 2},
+ {PI_CMD_WVAS, "WVAS", 141, 2},
+ {PI_CMD_WVBSY, "WVBSY", 101, 2},
+ {PI_CMD_WVCLR, "WVCLR", 101, 2},
+ {PI_CMD_WVCRE, "WVCRE", 101, 2},
+ {PI_CMD_WVDEL, "WVDEL", 112, 2},
+ {PI_CMD_WVGO, "WVGO" , 101, 2},
+ {PI_CMD_WVGOR, "WVGOR", 101, 2},
+ {PI_CMD_WVHLT, "WVHLT", 101, 2},
+ {PI_CMD_WVNEW, "WVNEW", 101, 2},
+ {PI_CMD_WVSC, "WVSC", 112, 2},
+ {PI_CMD_WVSM, "WVSM", 112, 2},
+ {PI_CMD_WVSP, "WVSP", 112, 2},
+ {PI_CMD_WVTX, "WVTX", 112, 2},
+ {PI_CMD_WVTXR, "WVTXR", 112, 2},
+
+ {PI_CMD_ADD , "ADD" , 111, 0},
+ {PI_CMD_AND , "AND" , 111, 0},
+ {PI_CMD_CALL , "CALL" , 114, 0},
+ {PI_CMD_CMP , "CMP" , 111, 0},
+ {PI_CMD_DCR , "DCR" , 113, 0},
+ {PI_CMD_DCRA , "DCRA" , 101, 0},
+ {PI_CMD_DIV , "DIV" , 111, 0},
+ {PI_CMD_HALT , "HALT" , 101, 0},
+ {PI_CMD_INR , "INR" , 113, 0},
+ {PI_CMD_INRA , "INRA" , 101, 0},
+ {PI_CMD_JM , "JM" , 114, 0},
+ {PI_CMD_JMP , "JMP" , 114, 0},
+ {PI_CMD_JNZ , "JNZ" , 114, 0},
+ {PI_CMD_JP , "JP" , 114, 0},
+ {PI_CMD_JZ , "JZ" , 114, 0},
+ {PI_CMD_LD , "LD" , 123, 0},
+ {PI_CMD_LDA , "LDA" , 111, 0},
+ {PI_CMD_MLT , "MLT" , 111, 0},
+ {PI_CMD_MOD , "MOD" , 111, 0},
+ {PI_CMD_OR , "OR" , 111, 0},
+ {PI_CMD_POP , "POP" , 113, 0},
+ {PI_CMD_POPA , "POPA" , 101, 0},
+ {PI_CMD_PUSH , "PUSH" , 113, 0},
+ {PI_CMD_PUSHA, "PUSHA", 101, 0},
+ {PI_CMD_RET , "RET" , 101, 0},
+ {PI_CMD_RL , "RL" , 123, 0},
+ {PI_CMD_RLA , "RLA" , 111, 0},
+ {PI_CMD_RR , "RR" , 123, 0},
+ {PI_CMD_RRA , "RRA" , 111, 0},
+ {PI_CMD_STA , "STA" , 113, 0},
+ {PI_CMD_SUB , "SUB" , 111, 0},
+ {PI_CMD_SYS , "SYS" , 116, 0},
+ {PI_CMD_TAG , "TAG" , 114, 0},
+ {PI_CMD_WAIT , "WAIT" , 111, 0},
+ {PI_CMD_X , "X" , 124, 0},
+ {PI_CMD_XA , "XA" , 113, 0},
+ {PI_CMD_XOR , "XOR" , 111, 0},
};
char * cmdUsage = "\
-BC1 v Clear gpios defined by mask v in bank 1.\n\
-BC2 v Clear gpios defined by mask v in bank 2.\n\
+BC1 v Clear gpios specified by mask v in bank 1.\n\
+BC2 v Clear gpios specified by mask v in bank 2.\n\
BR1 Read gpios bank 1.\n\
BR2 Read gpios bank 2.\n\
-BS1 v Set gpios defined by mask v in bank 1.\n\
-BS2 v Set gpios defined by mask v in bank 2.\n\
+BS1 v Set gpios specified by mask v in bank 1.\n\
+BS2 v Set gpios specified by mask v 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\
-MICRO v Delay for v microseconds.\n\
-MILLI v Delay for v milliseconds.\n\
+MICS v Delay for v microseconds.\n\
+MILS v Delay for v milliseconds.\n\
MODEG g Get gpio g mode.\n\
MODES g m Set gpio g to mode m.\n\
-NB h v Start notifications on handle h for gpios defined by mask v.\n\
+NB h v Start notifications on handle h for gpios specified by mask v.\n\
NC h Close notification handle h.\n\
NO Request notification handle.\n\
NP h Pause notifications on handle h.\n\
-P u v Set PWM value for user gpio u to d.\n\
+P u v Set PWM value for user gpio u to v.\n\
+PARSE t Validate script text t without storing.\n\
PFG u Get PWM frequency for user gpio u.\n\
-PFS u v Set PWM frequency for user gpio u to d.\n\
+PFS u v Set PWM frequency for user gpio u to v.\n\
PIGPV Return pigpio version.\n\
PRG u Get PWM range for user gpio u.\n\
PROC t Store text t of script.\n\
PROCR s pars Run script s with up to 10 optional parameters.\n\
PROCS s Stop script s.\n\
PRRG u Get PWM real range for user gpio u.\n\
-PRS u v Set PWM range for user gpio u to d.\n\
+PRS u v Set PWM range for user gpio u to v.\n\
PUD g p Set gpio pull up/down for gpio g to p.\n\
-PWM u v Set PWM value for user gpio u to d.\n\
+PWM u v Set PWM value for user gpio u to v.\n\
R g Read gpio g.\n\
READ g Read gpio g.\n\
-S u v Set servo value for user gpio u to d microseconds.\n\
-SERVO u v Set servo value for user gpio u to d microseconds.\n\
+S u v Set servo value for user gpio u to v microseconds.\n\
+SERVO u v Set servo value for user gpio u to v microseconds.\n\
SLR u v 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\
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 v Set watchdog of d milliseconds on user gpio u.\n\
+WDOG u v Set watchdog of v milliseconds on user gpio u.\n\
WRITE g L Write level L to gpio g.\n\
WVAG pulses Wave add generic pulses.\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\
+WVCRE Create wave from added pulses.\n\
+WVDEL w Delete waves w and higher.\n\
+WVGO Wave transmit (DEPRECATED).\n\
+WVGOR Wave transmit repeatedly (DEPRECATED).\n\
WVHLT Wave stop.\n\
+WVNEW Start a new empty wave.\n\
WVSC ws Wave get DMA control block stats.\n\
WVSM ws Wave get micros stats.\n\
WVSP ws Wave get pulses stats.\n\
+WVTX w Transmit wave w as one-shot.\n\
+WVTXR w Transmit wave w repeatedly.\n\
\n\
b = baud rate.\n\
g = any gpio (0-53).\n\
-h = handle (0-31).\n\
+h = handle (>=0).\n\
L = level (0-1).\n\
m = mode (RW540123).\n\
mask = a bit mask where (1<<g) is set for each gpio g of interest.\n\
-o = offset (0-).\n\
+o = offset (>=0).\n\
p = pud (ODU).\n\
pars = 0 to 10 parameters for script.\n\
-pl = pulse length (0-100).\n\
+pl = pulse length (1-50).\n\
pulses = 1 or more triplets of gpios on, gpios off, delay.\n\
-s = script id (0-31).\n\
+s = script id (>=0).\n\
t = text.\n\
u = user gpio (0-31).\n\
v = value.\n\
+w = wave id (>=0).\n\
ws = 0=now, 1=high, 2=max.\n\
\n\
Numbers may be entered as hex (prefix 0x), octal (prefix 0),\n\
{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_PULSELEN , "trigger pulse > 50 microseconds"},
{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"},
{PI_BAD_PARAM_NUM , "script parameter must be 0-9"},
- {PI_DUP_LABEL , "script has duplicate label"},
- {PI_TOO_MANY_LABELS , "script has too many labels"},
+ {PI_DUP_TAG , "script has duplicate tag"},
+ {PI_TOO_MANY_TAGS , "script has too many tags"},
{PI_BAD_SCRIPT_CMD , "illegal script command"},
{PI_BAD_VAR_NUM , "script variable must be 0-149"},
{PI_NO_SCRIPT_ROOM , "no more room for scripts"},
{PI_SOCK_WRIT_FAILED , "socket write failed"},
{PI_TOO_MANY_PARAM , "too many script parameters > 10"},
{PI_NOT_HALTED , "script already running or failed"},
+ {PI_BAD_TAG , "script has unresolved tag"},
+ {PI_BAD_MICS_DELAY , "bad MICS delay (too large)"},
+ {PI_BAD_MILS_DELAY , "bad MILS delay (too large)"},
+ {PI_BAD_WAVE_ID , "non existent wave id"},
+ {PI_TOO_MANY_CBS , "No more CBs for waveform"},
+ {PI_TOO_MANY_OOL , "No more OOL for waveform"},
+ {PI_EMPTY_WAVEFORM , "attempt to create an empty waveform"},
+ {PI_NO_WAVEFORM_ID , "no more waveform ids"},
};
{
if (strcasecmp(str, cmdInfo[i].name) == 0) return i;
}
- return -1;
+ return CMD_UNKNOWN_CMD;
}
-static int getNum(char *str, unsigned *val, uint8_t *opt, int flags)
+static int getNum(char *str, unsigned *val, int8_t *opt)
{
- int f, n, v;
+ int f, n;
+ unsigned v;
*opt = 0;
return n;
}
- if (flags & PARSE_FLAGS_PARAMS)
- {
- f = sscanf(str, " p%i %n", &v, &n);
+ f = sscanf(str, " v%i %n", &v, &n);
- if (f == 1)
- {
- *val = v;
- *opt = CMD_PARAM;
- return n;
- }
+ if (f == 1)
+ {
+ *val = v;
+ if (v < PI_MAX_SCRIPT_VARS) *opt = CMD_VAR;
+ else *opt = -CMD_VAR;
+ return n;
}
- if (flags & PARSE_FLAGS_VARS)
- {
- f = sscanf(str, " v%i %n", &v, &n);
+ f = sscanf(str, " p%i %n", &v, &n);
- if (f == 1)
- {
- *val = v;
- *opt = CMD_VAR;
- return n;
- }
+ if (f == 1)
+ {
+ *val = v;
+ if (v < PI_MAX_SCRIPT_PARAMS) *opt = CMD_PAR;
+ else *opt = -CMD_PAR;
+ return n;
}
return 0;
return intCmdStr;
}
-int cmdParse(char *buf, uint32_t *p, void **v, gpioCtlParse_t *ctl)
+int cmdParse(char *buf, uint32_t *p, void **v, cmdCtlParse_t *ctl)
{
int f, valid, idx, val, pp, pars, n, n2, i;
char *ptr;
char c;
- int param[MAX_PARAM];
+ int32_t param[MAX_PARAM];
bzero(&ctl->opt, sizeof(ctl->opt));
- sscanf(buf+ctl->eaten, " %31s", intCmdStr);
+ sscanf(buf+ctl->eaten, " %31s %n", intCmdStr, &pp);
+
+ ctl->eaten += pp;
p[0] = -1;
if (idx < 0) return idx;
- sscanf(buf+ctl->eaten, " %*31s %n", &pp);
-
- ctl->eaten += pp;
-
valid = 0;
p[0] = cmdInfo[idx].cmd;
switch (cmdInfo[idx].vt)
{
- case 1: /* BR1 BR2 HWVER NO PIGPV TICK WVBSY WVCLR WVGO
- WVGOR WVHLT
- */
+ case 101: /* BR1 BR2 DCRA H HALT HELP HWVER INRA NO
+ PIGPV POPA PUSHA RET T TICK WVBSY WVCLR
+ WVCRE WVGO WVGOR WVHLT WVNEW
+
+ No parameters, always valid.
+ */
valid = 1;
+
break;
- case 2: /* MODEG NC NP PFG PRG PROCD PROCS PRRG
- SLRC READ WVSC WVSM WVSP
- */
- ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0], ctl->flags);
- if (ctl->opt[0]) valid = 1;
+ case 111: /* ADD AND BC1 BC2 BS1 BS2 CMP DIV LDA MLT
+ MOD OR RLA RRA SUB WAIT XOR
+
+ One parameter, any value.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+
+ if (ctl->opt[0] > 0) valid = 1;
+
break;
- case 3: /* PFS PRS PWM SERVO SLR SLRO WDOG WRITE
- */
- ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0], ctl->flags);
- ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1], ctl->flags);
- if (ctl->opt[0] && ctl->opt[1]) valid = 1;
+ case 112: /* MG MICS MILS MODEG NC NP PFG PRG
+ PROCD PROCP PROCS PRRG R READ SLRC
+ WVDEL WVSC WVSM WVSP WVTX WVTXR
+
+ One positive parameter.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+
+ if ((ctl->opt[0] > 0) && ((int)p[1] >= 0)) valid = 1;
+
break;
- case 4: /* NB
- */
- ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0], ctl->flags);
- ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1], ctl->flags);
- if (ctl->opt[0] && ctl->opt[1]) valid = 1;
+ case 113: /* DCR INR POP PUSH STA XA
+
+ One register parameter.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+
+ if ((ctl->opt[0] > 0) && (p[1] < PI_MAX_SCRIPT_VARS)) valid = 1;
+
break;
- case 5: /* TRIG
- */
- ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0], ctl->flags);
- ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1], ctl->flags);
- ctl->eaten += getNum(buf+ctl->eaten, &p[3], &ctl->opt[2], ctl->flags);
- if (ctl->opt[0] && ctl->opt[1] && ctl->opt[2]) valid = 1;
+ case 114: /* CALL JM JMP JNZ JP JZ TAG
+
+ One numeric parameter, any value.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+ if (ctl->opt[0] == CMD_NUMERIC) valid = 1;
+
break;
- case 6: /* HELP
- */
+ case 115: /* PARSE PROC
+
+ One parameter, string (rest of input).
+ */
+ p[1] = strlen(buf+ctl->eaten);
+ v[1] = buf+ctl->eaten;
+ ctl->eaten += p[1];
+
valid = 1;
+
+ break;
+
+ case 116: /* SYS
+
+ One parameter, a string of letters, digits, '-' and '_'.
+ */
+ f = sscanf(buf+ctl->eaten, " %*s%n %n", &n, &n2);
+ if ((f >= 0) && n)
+ {
+ valid = 1;
+
+ for (i=0; i<n; i++)
+ {
+ c = buf[ctl->eaten+i];
+
+ if ((!isalnum(c)) && (c != '_') && (c != '-'))
+ {
+ valid = 0;
+ break;
+ }
+ }
+
+ if (valid)
+ {
+ p[1] = n;
+ ctl->opt[0] = CMD_NUMERIC;
+ v[1]=buf+ctl->eaten;
+ ctl->eaten += n2;
+ }
+ }
+
+ break;
+
+ case 121: /* P PFS PRS PWM S SERVO SLR SLRO W WDOG WRITE
+
+ Two positive parameters.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+ ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1]);
+
+ if ((ctl->opt[0] > 0) && ((int)p[1] >= 0) &&
+ (ctl->opt[1] > 0) && ((int)p[2] >= 0)) valid = 1;
+
break;
- case 7: /* BC1 BC2 BS1 BS2
- */
- ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0], ctl->flags);
- if (ctl->opt[0]) valid = 1;
+ case 122: /* NB
+
+ Two parameters, first positive, second any value.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+ ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1]);
+
+ if ((ctl->opt[0] > 0) && ((int)p[1] >= 0) &&
+ (ctl->opt[1] > 0)) valid = 1;
+
+ break;
+
+ case 123: /* LD RL RR
+
+ Two parameters, first register, second any value.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+ ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1]);
+
+ if ((ctl->opt[0] > 0) &&
+ (p[1] < PI_MAX_SCRIPT_VARS) &&
+ (ctl->opt[1] > 0)) valid = 1;
+
break;
- case 8: /* MODES
- */
- ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0], ctl->flags);
+ case 124: /* X
+
+ Two register parameters.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+ ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1]);
+
+ if ((ctl->opt[0] > 0) && (p[1] < PI_MAX_SCRIPT_VARS) &&
+ (ctl->opt[1] > 0) && (p[2] < PI_MAX_SCRIPT_VARS)) valid = 1;
+
+ break;
+
+ case 125: /* M MODES
+
+ Two parameters, first positive, second in 'RW540123'.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+
f = sscanf(buf+ctl->eaten, " %c %n", &c, &n);
- if (ctl->opt[0] && (f >= 1))
+
+ if ((ctl->opt[0] > 0) && ((int)p[1] >= 0) && (f >= 1))
{
ctl->eaten += n;
val = toupper(c);
ptr = strchr(fmtMdeStr, val);
+
if (ptr != NULL)
{
val = ptr - fmtMdeStr;
valid = 1;
}
}
+
break;
- case 9: /* PUD
- */
- ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0], ctl->flags);
+ case 126: /* PUD
+
+ Two parameters, first positive, second in 'ODU'.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+
f = sscanf(buf+ctl->eaten, " %c %n", &c, &n);
- if (ctl->opt[0] && (f >= 1))
+
+ if ((ctl->opt[0] > 0) && ((int)p[1] >= 0) && (f >= 1))
{
ctl->eaten += n;
val = toupper(c);
valid = 1;
}
}
+
break;
- case 10: /* PROC
- */
- p[1] = strlen(buf+ctl->eaten);
- v[1] = buf+ctl->eaten;
- ctl->eaten += p[1];
- valid = 1;
+ case 131: /* TRIG
+
+ Three positive parameters.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+ ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1]);
+ ctl->eaten += getNum(buf+ctl->eaten, &p[3], &ctl->opt[2]);
+
+ if ((ctl->opt[0] > 0) && ((int)p[1] >= 0) &&
+ (ctl->opt[1] > 0) && ((int)p[2] >= 0) &&
+ (ctl->opt[2] == CMD_NUMERIC) && ((int)p[3] >= 0))
+ valid = 1;
+
break;
- case 11: /* WVAS
- */
- ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0], ctl->flags);
- ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1], ctl->flags);
- ctl->eaten += getNum(buf+ctl->eaten, &p[3], &ctl->opt[2], ctl->flags);
+ case 141: /* WVAS
- if (ctl->opt[0] && ctl->opt[1] && ctl->opt[2])
+ Four parameters, first two positive, third any value,
+ last string (rest of input).
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+ ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1]);
+ ctl->eaten += getNum(buf+ctl->eaten, &p[3], &ctl->opt[2]);
+
+ if ((ctl->opt[0] == CMD_NUMERIC) && ((int)p[1] >= 0) &&
+ (ctl->opt[1] == CMD_NUMERIC) && ((int)p[2] >= 0) &&
+ (ctl->opt[2] == CMD_NUMERIC))
{
p[4] = strlen(buf+ctl->eaten);
v[1] = buf+ctl->eaten;
ctl->eaten += p[4];
valid = 1;
}
+
break;
- case 12: /* PROCR
- */
- ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0], 0);
+ case 191: /* PROCR
- pars = 0;
+ One to 11 parameters, first positive,
+ optional remainder, any value.
+ */
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
- while (pars < 10)
+ if ((ctl->opt[0] == CMD_NUMERIC) && ((int)p[1] >= 0))
{
- ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1], 0);
- if (ctl->opt[1]) param[pars++] = p[2];
- else break;
- }
+ pars = 0;
- p[2] = pars;
+ while (pars < PI_MAX_SCRIPT_PARAMS)
+ {
+ ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[1]);
+ if (ctl->opt[1] == CMD_NUMERIC) param[pars++] = p[2];
+ else break;
+ }
- v[1] = param;
+ p[2] = pars;
+
+ v[1] = param;
+
+ valid = 1;
+ }
- if (ctl->opt[0]) valid = 1;
break;
- case 13: /* WVAG
- */
+ case 192: /* WVAG
+
+ One or more triplets (gpios on, gpios off, delay),
+ any value.
+ */
pars = 0;
while (pars < MAX_PARAM)
{
- ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0], 0);
- if (ctl->opt[0]) param[pars++] = p[1];
+ ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[0]);
+ if (ctl->opt[0] == CMD_NUMERIC) param[pars++] = p[1];
else break;
}
- p[1] = pars/3;
+ p[1] = pars / 3;
v[1] = param;
- if (pars && ((pars%3)==0)) valid = 1;
- break;
+ if (pars && ((pars % 3) == 0)) valid = 1;
- case 20: /*
- */
- f = sscanf(buf+ctl->eaten, " %d %n", &p[1], &n);
- if ((f >= 1) && (p[1] >= 0) && (p[1] < MAX_SCRIPT_VARS))
- {
- ctl->eaten += n;
- valid = 1;
- }
break;
- case 21: /*
- */
- f = sscanf(buf+ctl->eaten, " %d %n", &p[1], &n);
- if (f == 1)
- {
- ctl->eaten += n;
- valid = 1;
- }
- break;
- case 22: /*
- */
- f = sscanf(buf+ctl->eaten, " %d %n", &p[1], &n);
- if (f == 1)
- {
- ctl->eaten += n;
- valid = 1;
- }
- break;
+ }
- case 23: /*
- */
- valid = 1;
- break;
+ if (valid) return idx; else return CMD_BAD_PARAMETER;
+}
- case 24: /*
- */
- f = sscanf(buf+ctl->eaten, " %d %d %n", &p[1], &p[2], &n);
- if ((f >= 2) &&
- (p[1] >= 0) && (p[1] < MAX_SCRIPT_VARS) &&
- (p[2] >= 0) && (p[2] < MAX_SCRIPT_VARS))
- {
- ctl->eaten += n;
- valid = 1;
- }
- break;
+char * cmdErrStr(int error)
+{
+ int i;
- case 25: /*
- */
- f = sscanf(buf+ctl->eaten, " %d %n", &p[1], &n);
- if ((f >= 1) && (p[1] >= 0) && (p[1] < MAX_SCRIPT_PARAMS))
- {
- ctl->eaten += n;
- valid = 1;
- }
- break;
+ for (i=0; i<(sizeof(errInfo)/sizeof(errInfo_t)); i++)
+ {
+ if (errInfo[i].error == error) return errInfo[i].str;
+ }
+ return "unknown error";
+}
- case 26: /*
- */
- f = sscanf(buf+ctl->eaten, " %d %n", &p[1], &n);
- if (f >= 1)
- {
- ctl->eaten += n;
- valid = 1;
- }
- break;
+int cmdParseScript(char *script, cmdScript_t *s, int diags)
+{
+ int idx, len, b, i, j, tags, resolved;
+ int status;
+ uint32_t p[10];
+ void *v[10];
+ cmdInstr_t instr;
+ cmdCtlParse_t ctl;
- case 27: /*
- */
- f = sscanf(buf+ctl->eaten, " %*s%n %n", &n, &n2);
- if ((f >= 0) && n)
+ ctl.eaten = 0;
+
+ status = 0;
+
+ cmdTagStep_t tag_step[PI_MAX_SCRIPT_TAGS];
+
+ len = strlen(script);
+
+ /* calloc space for PARAMS, VARS, CMDS, and STRINGS */
+
+ b = (sizeof(int) * (PI_MAX_SCRIPT_PARAMS + PI_MAX_SCRIPT_VARS)) +
+ (sizeof(cmdInstr_t) * (len + 2) / 2) + len;
+
+ s->par = calloc(b, 1);
+
+ if (s->par == NULL) return -1;
+
+ s->var = s->par + PI_MAX_SCRIPT_PARAMS;
+
+ s->instr = (cmdInstr_t *)(s->var + PI_MAX_SCRIPT_VARS);
+
+ s->str_area = (char *)(s->instr + ((len + 2) / 2));
+
+ s->str_area_len = len;
+ s->str_area_pos = 0;
+
+ s->instrs = 0;
+
+ tags = 0;
+
+ idx = 0;
+
+ while (ctl.eaten<len)
+ {
+ idx = cmdParse(script, p, v, &ctl);
+
+ memcpy(&instr.p, p, sizeof(instr.p));
+
+ if (idx >= 0)
+ {
+ switch (instr.p[0])
{
- valid = 1;
+ case PI_CMD_HELP:
+ case PI_CMD_PARSE:
+ case PI_CMD_PROC:
+ case PI_CMD_PROCD:
+ case PI_CMD_PROCP:
+ case PI_CMD_PROCR:
+ case PI_CMD_PROCS:
+ case PI_CMD_SLR:
+ case PI_CMD_SLRC:
+ case PI_CMD_SLRO:
+ case PI_CMD_WVAG:
+ case PI_CMD_WVAS:
+
+ if (diags)
+ {
+ fprintf(stderr, "Illegal command: %s\n", cmdStr());
+ }
- for (i=0; i<n; i++)
- {
- c = buf[ctl->eaten+i];
+ if (!status) status = PI_BAD_SCRIPT_CMD;
+ idx = -1;
- if ((!isalnum(c)) && (c != '_') && (c != '-'))
+ break;
+
+ case PI_CMD_TAG:
+
+ if (tags < PI_MAX_SCRIPT_TAGS)
{
- valid = 0;
- break;
+ /* check tag not already used */
+ for (j=0; j<tags; j++)
+ {
+ if (tag_step[j].tag == instr.p[1])
+ {
+ if (diags)
+ {
+ fprintf(stderr, "Duplicate tag: %d\n", instr.p[1]);
+ }
+
+ if (!status) status = PI_DUP_TAG;
+ idx = -1;
+ }
+ }
+
+ tag_step[tags].tag = instr.p[1];
+ tag_step[tags].step = s->instrs;
+ tags++;
+ }
+ else
+ {
+ if (diags)
+ {
+ fprintf(stderr, "Too many tags: %d\n", instr.p[1]);
+ }
+ if (!status) status = PI_TOO_MANY_TAGS;
+ idx = -1;
}
- }
- if (valid)
- {
- p[1] = n;
- ctl->opt[0] = CMD_NUMERIC;
- v[1]=buf+ctl->eaten;
- ctl->eaten += n2;
- }
+ break;
+
+ case PI_CMD_SYS:
+
+ strncpy(s->str_area+s->str_area_pos, v[1], p[1]);
+ s->str_area[s->str_area_pos+p[1]] = 0;
+ instr.p[1] = (intptr_t) s->str_area+s->str_area_pos;
+ s->str_area_pos += (p[1] + 1);
+
+ break;
+
}
- break;
+ }
+ else
+ {
+ if (diags)
+ {
+ if (idx == CMD_UNKNOWN_CMD)
+ fprintf(stderr, "Unknown command: %s\n", cmdStr());
+ else
+ fprintf(stderr, "Bad parameter to %s\n", cmdStr());
+ }
+ if (!status) status = PI_BAD_SCRIPT_CMD;
+ }
- case 28: /*
- */
- f = sscanf(buf+ctl->eaten, " %d %d %n", &p[1], &p[2], &n);
- if ((f >= 2) && (p[1] >= 0) && (p[1] < MAX_SCRIPT_VARS))
+ if (idx >= 0)
+ {
+ if (instr.p[0] != PI_CMD_TAG)
{
- ctl->eaten += n;
- valid = 1;
+ memcpy(instr.opt, &ctl.opt, sizeof(instr.opt));
+ s->instr[s->instrs++] = instr;
}
- break;
+ }
}
- if (valid) return idx; else return -1;
-}
+ for (i=0; i<s->instrs; i++)
+ {
+ instr = s->instr[i];
-char * cmdErrStr(int error)
-{
- int i;
+ /* resolve jumps */
- for (i=0; i<(sizeof(errInfo)/sizeof(errInfo_t)); i++)
- {
- if (errInfo[i].error == error) return errInfo[i].str;
+ if ((instr.p[0] == PI_CMD_JMP) || (instr.p[0] == PI_CMD_CALL) ||
+ (instr.p[0] == PI_CMD_JZ) || (instr.p[0] == PI_CMD_JNZ) ||
+ (instr.p[0] == PI_CMD_JM) || (instr.p[0] == PI_CMD_JP))
+ {
+ resolved = 0;
+
+ for (j=0; j<tags; j++)
+ {
+ if (instr.p[1] == tag_step[j].tag)
+ {
+ s->instr[i].p[1] = tag_step[j].step;
+ resolved = 1;
+ break;
+ }
+ }
+
+ if (!resolved)
+ {
+ if (diags)
+ {
+ fprintf(stderr, "Can't resolve tag %d\n", instr.p[1]);
+ }
+ if (!status) status = PI_BAD_TAG;
+ }
+ }
}
- return "unknown error";
+ return status;
}
*/
/*
-This version is for pigpio version 13+
+This version is for pigpio version 14+
*/
#ifndef COMMAND_H
#define MAX_PARAM 512
-#define PARSE_FLAGS_PARAMS 1
-#define PARSE_FLAGS_VARS 2
+#define CMD_UNKNOWN_CMD -1
+#define CMD_BAD_PARAMETER -2
#define CMD_NUMERIC 1
-#define CMD_PARAM 2
-#define CMD_VAR 3
+#define CMD_VAR 2
+#define CMD_PAR 3
typedef struct
{
- int flags;
- int eaten;
- uint8_t opt[8];
-} gpioCtlParse_t;
+ int eaten;
+ int8_t opt[4];
+} cmdCtlParse_t;
typedef struct
{
int rv; /* command return value type */
} cmdInfo_t;
+typedef struct
+{
+ uint32_t tag;
+ int step;
+} cmdTagStep_t;
+
+typedef struct
+{
+ uint32_t p[7];
+ int8_t opt[4];
+} cmdInstr_t;
+
+typedef struct
+{
+ /*
+ +-----------+---------+---------+----------------+
+ | PARAMS... | VARS... | CMDS... | STRING AREA... |
+ +-----------+---------+---------+----------------+
+ */
+ int *par;
+ int *var;
+ cmdInstr_t *instr;
+ int instrs;
+ char *str_area;
+ int str_area_len;
+ int str_area_pos;
+} cmdScript_t;
+
extern cmdInfo_t cmdInfo[];
extern char *cmdUsage;
-int cmdParse(char *buf, uint32_t *p, void **v, gpioCtlParse_t *ctlParse);
+int cmdParse(char *buf, uint32_t *p, void **v, cmdCtlParse_t *ctl);
+
+int cmdParseScript(char *script, cmdScript_t *s, int diags);
char *cmdErrStr(int error);
For more information, please refer to <http://unlicense.org/>
*/
-/* pigpio version 13 */
+/* pigpio version 14 */
#include <stdio.h>
#include <string.h>
#define DMAO_PAGES (PAGES_PER_BLOCK * PI_WAVE_BLOCKS)
-#define NUM_OOL (DMAO_PAGES * OOL_PER_OPAGE)
+#define NUM_WAVE_OOL (DMAO_PAGES * OOL_PER_OPAGE)
+#define NUM_WAVE_CBS (DMAO_PAGES * CBS_PER_OPAGE)
#define TICKSLOTS 50
#define SRX_BUF_SIZE 8192
#define CMD_BUF_SIZE 4096
+#define MAX_DELAY 50
+
/* --------------------------------------------------------------- */
typedef void (*callbk_t) ();
-typedef struct { /* linux/arch/arm/mach-bcm2708/include/mach/dma.h */
- unsigned long info;
- unsigned long src;
- unsigned long dst;
- unsigned long length;
- unsigned long stride;
- unsigned long next;
- unsigned long pad[2];
-} dmaCbs_t;
-
typedef struct
{
- dmaCbs_t cb [128];
+ rawCbs_t cb [128];
} dmaPage_t;
typedef struct
{
- dmaCbs_t cb [CBS_PER_IPAGE];
+ rawCbs_t cb [CBS_PER_IPAGE];
uint32_t level [LVS_PER_IPAGE];
uint32_t gpioOff [OFF_PER_IPAGE];
uint32_t tick [TCK_PER_IPAGE];
typedef struct
{
- dmaCbs_t cb [CBS_PER_OPAGE];
+ rawCbs_t cb [CBS_PER_OPAGE];
uint32_t OOL [OOL_PER_OPAGE];
uint32_t periphData;
} dmaOPage_t;
uint32_t bits;
} gpioGetSamples_t;
-typedef struct
-{
- uint32_t label;
- int step;
-} gpioLabelStep_t;
-
typedef struct
{
callbk_t func;
#define PI_SCRIPT_RUN 1
#define PI_SCRIPT_DELETE 2
-#define PI_SCRIPT_SLOTS 32
-
#define PI_SCRIPT_STACK_SIZE 256
-typedef struct
-{
- uint32_t p[6];
- uint8_t opt[8];
-} gpioInstr_t;
-
typedef struct
{
unsigned id;
pthread_t *pthIdp;
pthread_mutex_t pthMutex;
pthread_cond_t pthCond;
-/*
- +-----------+---------+---------+----------------+
- | PARAMS... | VARS... | CMDS... | STRING AREA... |
- +-----------+---------+---------+----------------+
-*/
- int *param;
- int *var;
- gpioInstr_t *instr;
- int instrs;
- char *str_area;
- int str_area_len;
- int str_area_pos;
+ cmdScript_t script;
} gpioScript_t;
int mode;
} wfRx_t;
+typedef struct
+{
+ int botCB; /* first CB used by wave */
+ int topCB; /* last CB used by wave */
+ int botOOL;
+ int topOOL;
+} waveInfo_t;
/* --------------------------------------------------------------- */
0, 0, (DMAO_PAGES * CBS_PER_OPAGE)
};
+static waveInfo_t waveInfo[PI_MAX_WAVES];
+
static volatile wfRx_t wfRx[PI_MAX_USER_GPIO+1];
+static int waveOutBotCB = 0;
+static int waveOutTopCB = NUM_WAVE_CBS;
+static int waveOutBotOOL = 0;
+static int waveOutTopOOL = NUM_WAVE_OOL;
+static int waveOutCount = 0;
+
static volatile uint32_t alertBits = 0;
static volatile uint32_t monitorBits = 0;
static volatile uint32_t notifyBits = 0;
static gpioNotify_t gpioNotify [PI_NOTIFY_SLOTS];
-static gpioScript_t gpioScript [PI_SCRIPT_SLOTS];
+static gpioScript_t gpioScript [PI_MAX_SCRIPTS];
static gpioSignal_t gpioSignal [PI_MAX_SIGNUM+1];
start = systReg[SYST_CLO];
- if (micros < 101) while ((systReg[SYST_CLO] - start) <= micros) ;
+ if (micros <= MAX_DELAY) while ((systReg[SYST_CLO] - start) <= micros) ;
else myGpioSleep(micros/MILLION, micros%MILLION);
return tick;
}
-/* ----------------------------------------------------------------------- */
-
-static int myParseScript(char *script, gpioScript_t *s)
+static int myPermit(unsigned gpio)
{
- int idx, len, b, i, j, labels, resolved, pos;
- int status;
- uint32_t p[10];
- void *v[10];
- gpioInstr_t instr;
- gpioCtlParse_t ctl;
-
- ctl.flags = PARSE_FLAGS_PARAMS | PARSE_FLAGS_VARS;
- ctl.eaten = 0;
-
- status = 0;
-
- gpioLabelStep_t label_step[MAX_SCRIPT_LABELS];
-
- len = strlen(script);
-
- /* calloc space for PARAMS, VARS, CMDS, and STRINGS */
-
- b = (sizeof(int) * (MAX_SCRIPT_PARAMS + MAX_SCRIPT_VARS)) +
- (sizeof(gpioInstr_t) * (len + 2) / 2) + len;
-
- s->param = calloc(b, 1);
-
- if (s->param == NULL) return -1;
-
- s->var = s->param + MAX_SCRIPT_PARAMS;
-
- s->instr = (gpioInstr_t *)(s->var + MAX_SCRIPT_VARS);
-
- s->str_area = (char *)(s->instr + ((len + 2) / 2));
-
- s->str_area_len = len;
- s->str_area_pos = 0;
-
- s->instrs = 0;
-
- labels = 0;
-
- idx = 0;
-
- while (!status && ((ctl.eaten)<len) && (idx >= 0))
- {
- pos = ctl.eaten;
-
- idx = cmdParse(script, p, v, &ctl);
-
- memcpy(&instr.p, p, sizeof(instr.p));
-
- if (idx >= 0)
- {
- switch (instr.p[0])
- {
- case PI_CMD_LABEL:
-
- if (labels < MAX_SCRIPT_LABELS)
- {
- /* check label not already used */
- for (j=0; j<labels; j++)
- {
- if (label_step[j].label == instr.p[1])
- {
- DBG(DBG_USER, "duplicate label: %s", script+pos);
- status = PI_DUP_LABEL;
- idx = -1;
- }
- }
-
- label_step[labels].label = instr.p[1];
- label_step[labels].step = s->instrs;
- labels++;
- }
- else
- {
- DBG(DBG_USER, "too many labels: %s", script+pos);
- status = PI_TOO_MANY_LABELS;
- idx = -1;
- }
-
- break;
-
- case PI_CMD_SYS:
-
- strncpy(s->str_area+s->str_area_pos, v[1], p[1]);
- s->str_area[s->str_area_pos+p[1]] = 0;
- instr.p[1] = (int) s->str_area+s->str_area_pos;
- s->str_area_pos += (p[1] + 1);
-
- break;
-
- case PI_CMD_TRIG:
- break;
-
- }
- }
- else
- {
- DBG(DBG_USER, "invalid command: %s", script+pos);
- status = PI_BAD_SCRIPT_CMD;
- }
-
- if (idx >= 0)
- {
- if (instr.p[0] != PI_CMD_LABEL)
- {
- memcpy(instr.opt, &ctl.opt, sizeof(instr.opt));
- s->instr[s->instrs++] = instr;
- }
- }
- }
-
- DBG(DBG_SCRIPT, "status=%d eaten=%d len=%d idx=%d",
- status, ctl.eaten, len, idx);
-
- for (i=0; i<s->instrs; i++)
- {
- instr = s->instr[i];
-
- /* resolve jumps */
-
- if ((instr.p[0] == PI_CMD_JMP) || (instr.p[0] == PI_CMD_CALL) ||
- (instr.p[0] == PI_CMD_JZ) || (instr.p[0] == PI_CMD_JNZ) ||
- (instr.p[0] == PI_CMD_JM) || (instr.p[0] == PI_CMD_JP))
- {
- resolved = 0;
-
- for (j=0; j<labels; j++)
- {
- if (instr.p[1] == label_step[j].label)
- {
- s->instr[i].p[1] = label_step[j].step;
- resolved = 1;
- break;
- }
- }
-
- if (!resolved)
- {
- DBG(DBG_USER, "can't resolve label %d\n", instr.p[1]);
- status = PI_BAD_SCRIPT;
- }
- }
- }
- return status;
+ if (gpioMask & ((uint64_t)(1)<<gpio)) return 1; else return 0;
}
/* ----------------------------------------------------------------------- */
case PI_CMD_HWVER: res = gpioHardwareRevision(); break;
- case PI_CMD_MICRO: myGpioDelay(p[1]); break;
+ case PI_CMD_MICS:
+ if (p[1] <= PI_MAX_MICS_DELAY) myGpioDelay(p[1]);
+ else res = PI_BAD_MICS_DELAY;
+ break;
- case PI_CMD_MILLI: myGpioDelay(p[1] * 1000); break;
+ case PI_CMD_MILS:
+ if (p[1] <= PI_MAX_MILS_DELAY) myGpioDelay(p[1] * 1000);
+ else res = PI_BAD_MILS_DELAY;
+ break;
case PI_CMD_MODEG: res = gpioGetMode(p[1]); break;
case PI_CMD_MODES:
- if (gpioMask & (uint64_t)(1<<p[1])) res = gpioSetMode(p[1], p[2]);
+ if (myPermit(p[1])) res = gpioSetMode(p[1], p[2]);
else
{
DBG(DBG_USER, "gpioSetMode: gpio %d, no permission to update", p[1]);
case PI_CMD_PFG: res = gpioGetPWMfrequency(p[1]); break;
case PI_CMD_PFS:
- if (gpioMask & (uint64_t)(1<<p[1])) res = gpioSetPWMfrequency(p[1], p[2]);
+ if (myPermit(p[1])) res = gpioSetPWMfrequency(p[1], p[2]);
else
{
DBG(DBG_USER,
case PI_CMD_PRRG: res = gpioGetPWMrealRange(p[1]); break;
case PI_CMD_PRS:
- if (gpioMask & (uint64_t)(1<<p[1])) res = gpioSetPWMrange(p[1], p[2]);
+ if (myPermit(p[1])) res = gpioSetPWMrange(p[1], p[2]);
else
{
DBG(DBG_USER,
break;
case PI_CMD_PUD:
- if (gpioMask & (uint64_t)(1<<p[1])) res = gpioSetPullUpDown(p[1], p[2]);
+ if (myPermit(p[1])) res = gpioSetPullUpDown(p[1], p[2]);
else
{
DBG(DBG_USER,
break;
case PI_CMD_PWM:
- if (gpioMask & (uint64_t)(1<<p[1])) res = gpioPWM(p[1], p[2]);
+ if (myPermit(p[1])) res = gpioPWM(p[1], p[2]);
else
{
DBG(DBG_USER, "gpioPWM: gpio %d, no permission to update", p[1]);
case PI_CMD_READ: res = gpioRead(p[1]); break;
case PI_CMD_SERVO:
- if (gpioMask & (uint64_t)(1<<p[1])) res = gpioServo(p[1], p[2]);
+ if (myPermit(p[1])) res = gpioServo(p[1], p[2]);
else
{
DBG(DBG_USER, "gpioServo: gpio %d, no permission to update", p[1]);
case PI_CMD_TICK: res = gpioTick(); break;
case PI_CMD_TRIG:
- if (gpioMask & (uint64_t)(1<<p[1]))
- res = gpioTrigger(p[1], p[2], p[3]);
+ if (myPermit(p[1])) res = gpioTrigger(p[1], p[2], p[3]);
else
{
DBG(DBG_USER, "gpioTrigger: gpio %d, no permission to update", p[1]);
case PI_CMD_WDOG: res = gpioSetWatchdog(p[1], p[2]); break;
case PI_CMD_WRITE:
- if (gpioMask & (uint64_t)(1<<p[1])) res = gpioWrite(p[1], p[2]);
+ if (myPermit(p[1])) res = gpioWrite(p[1], p[2]);
else
{
DBG(DBG_USER, "gpioWrite: gpio %d, no permission to update", p[1]);
break;
case PI_CMD_WVAS:
- if (gpioMask & (uint64_t)(1<<p[1]))
+ if (myPermit(p[1]))
res = gpioWaveAddSerial(p[1], p[2], p[3], p[4], (char *)p[5]);
else
{
case PI_CMD_WVCLR: res = gpioWaveClear(); break;
+ case PI_CMD_WVCRE: res = gpioWaveCreate(); break;
+
+ case PI_CMD_WVDEL: res = gpioWaveDelete(p[1]); 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_WVNEW: res = gpioWaveAddNew(); break;
+
case PI_CMD_WVSC:
switch(p[1])
{
case 0: res = gpioWaveGetCbs(); break;
case 1: res = gpioWaveGetHighCbs(); break;
case 2: res = gpioWaveGetMaxCbs(); break;
- default: res = -9999;
+ default: res = PI_BAD_WVSC_COMMND;
}
break;
case 0: res = gpioWaveGetMicros(); break;
case 1: res = gpioWaveGetHighMicros(); break;
case 2: res = gpioWaveGetMaxMicros(); break;
- default: res = -9999;
+ default: res = PI_BAD_WVSM_COMMND;
}
break;
case 0: res = gpioWaveGetPulses(); break;
case 1: res = gpioWaveGetHighPulses(); break;
case 2: res = gpioWaveGetMaxPulses(); break;
- default: res = -9999;
+ default: res = PI_BAD_WVSP_COMMND;
}
break;
+
+ case PI_CMD_WVTX:
+ res = gpioWaveTxSend(p[1], PI_WAVE_MODE_ONE_SHOT); break;
+
+ case PI_CMD_WVTXR:
+ res = gpioWaveTxSend(p[1], PI_WAVE_MODE_REPEAT); break;
+
}
return (res);
}
/* ======================================================================= */
-static dmaCbs_t * waveCbVOadr(int pos)
+rawCbs_t * rawWaveCBAdr(int n)
{
int page, slot;
- page = pos/CBS_PER_OPAGE;
- slot = pos%CBS_PER_OPAGE;
+ page = n/CBS_PER_OPAGE;
+ slot = n%CBS_PER_OPAGE;
return &dmaOVirt[page]->cb[slot];
}
static void waveCbOPrint(int pos)
{
- dmaCbs_t * p;
+ rawCbs_t * p;
- p = waveCbVOadr(pos);
+ p = rawWaveCBAdr(pos);
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);
bitDelay[9] = (e-s)/100;
}
+static int errCBsOOL(int cb, int botOOL, int topOOL)
+{
+ if (cb >= waveOutTopCB) return PI_TOO_MANY_CBS;
+
+ if (botOOL >= topOOL) return PI_TOO_MANY_OOL;
+
+ return 0;
+}
+
/* ----------------------------------------------------------------------- */
static int wave2Cbs(unsigned mode)
{
- int cb=0, onoff=0, level=NUM_OOL;
+ int botCB=waveOutBotCB, botOOL=waveOutBotOOL, topOOL=waveOutTopOOL;
- dmaCbs_t *p=NULL;
+ int status;
+
+ rawCbs_t *p=NULL;
- unsigned i, half, repeatCb;
+ unsigned i, half, repeatCB;
unsigned numWaves;
half = PI_WF_MICROS/2;
+ if ((status = errCBsOOL(botCB+1, botOOL, topOOL))) return status;
+
/* add delay cb at start of DMA */
- p = waveCbVOadr(cb++);
+ p = rawWaveCBAdr(botCB++);
/* use the secondary clock */
p->info = NORMAL_DMA |
DMA_DEST_DREQ |
DMA_PERIPHERAL_MAPPING(2);
-
p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | 0x7e000000;
}
else
p->info = NORMAL_DMA |
DMA_DEST_DREQ |
DMA_PERIPHERAL_MAPPING(5);
-
p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | 0x7e000000;
}
p->src = (uint32_t) (&dmaOPhys[0]->periphData) | DMA_BUS_ADR;
- p->length = 4 * 50 / PI_WF_MICROS; /* 50 micros delay */
- p->next = waveCbPOadr(cb) | DMA_BUS_ADR;
+ p->length = 4 * 20 / PI_WF_MICROS; /* 20 micros delay */
+ p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
- repeatCb = cb;
+ repeatCB = botCB;
for (i=0; i<numWaves; i++)
{
if (waves[i].gpioOn)
{
- waveSetOOL(onoff, waves[i].gpioOn);
+ if ((status = errCBsOOL(botCB+1, botOOL+1, topOOL))) return status;
+
+ waveSetOOL(botOOL, waves[i].gpioOn);
- p = waveCbVOadr(cb++);
+ p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
- p->src = waveOOLPOadr(onoff++) | DMA_BUS_ADR;
+ p->src = waveOOLPOadr(botOOL++) | DMA_BUS_ADR;
p->dst = ((GPIO_BASE + (GPSET0*4)) & 0x00ffffff) | 0x7e000000;
p->length = 4;
- p->next = waveCbPOadr(cb) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
}
if (waves[i].gpioOff)
{
- waveSetOOL(onoff, waves[i].gpioOff);
+ if ((status = errCBsOOL(botCB+1, botOOL+1, topOOL))) return status;
- p = waveCbVOadr(cb++);
+ waveSetOOL(botOOL, waves[i].gpioOff);
+
+ p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
- p->src = waveOOLPOadr(onoff++) | DMA_BUS_ADR;
+ p->src = waveOOLPOadr(botOOL++) | DMA_BUS_ADR;
p->dst = ((GPIO_BASE + (GPCLR0*4)) & 0x00ffffff) | 0x7e000000;
p->length = 4;
- p->next = waveCbPOadr(cb) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
}
if (waves[i].flags & WAVE_FLAG_READ)
{
- p = waveCbVOadr(cb++);
+ if ((status = errCBsOOL(botCB+1, botOOL, topOOL-1))) return status;
+
+ p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
p->src = ((GPIO_BASE + (GPLEV0*4)) & 0x00ffffff) | 0x7e000000;
- p->dst = waveOOLPOadr(--level) | DMA_BUS_ADR;
+ p->dst = waveOOLPOadr(--topOOL) | DMA_BUS_ADR;
p->length = 4;
- p->next = waveCbPOadr(cb) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
}
if (waves[i].flags & WAVE_FLAG_TICK)
{
- p = waveCbVOadr(cb++);
+ if ((status = errCBsOOL(botCB+1, botOOL, topOOL-1))) return status;
+
+ p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
p->src = ((SYST_BASE + (SYST_CLO*4)) & 0x00ffffff) | 0x7e000000;
- p->dst = waveOOLPOadr(--level) | DMA_BUS_ADR;
+ p->dst = waveOOLPOadr(--topOOL) | DMA_BUS_ADR;
p->length = 4;
- p->next = waveCbPOadr(cb) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
}
if (waves[i].usDelay)
{
- p = waveCbVOadr(cb++);
+ if ((status = errCBsOOL(botCB+1, botOOL, topOOL))) return status;
+
+ p = rawWaveCBAdr(botCB++);
/* use the secondary clock */
p->src = (uint32_t) (&dmaOPhys[0]->periphData) | DMA_BUS_ADR;
p->length = 4 * ((waves[i].usDelay+half)/PI_WF_MICROS);
- p->next = waveCbPOadr(cb) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
}
}
{
if (mode == PI_WAVE_MODE_ONE_SHOT)
p->next = 0;
- else p->next = waveCbPOadr(repeatCb) | DMA_BUS_ADR;
+ else p->next = waveCbPOadr(repeatCB) | DMA_BUS_ADR;
}
- return cb;
+ status = botCB - waveOutBotCB;
+
+ waveOutBotCB = botCB;
+ waveOutBotOOL = botOOL;
+ waveOutTopOOL = topOOL;
+
+ return status;
}
static int waveMerge(unsigned numIn1, gpioWave_t *in1)
{
- unsigned inPos1=0, inPos2=0, outPos=0, level = NUM_OOL;
+ unsigned inPos1=0, inPos2=0, outPos=0, level = NUM_WAVE_OOL;
unsigned cbs=0;
/* ======================================================================= */
-static dmaCbs_t * dmaCB2adr(int pos)
+static rawCbs_t * dmaCB2adr(int pos)
{
int page, slot;
static void dmaCbPrint(int pos)
{
- dmaCbs_t * p;
+ rawCbs_t * p;
p = dmaCB2adr(pos);
/* ----------------------------------------------------------------------- */
-unsigned dmaNowAtOCB(void)
+unsigned rawWaveCB(void)
{
unsigned cb;
static unsigned lastPage=0;
static void dmaGpioOnCb(int b, int pos)
{
- dmaCbs_t * p;
+ rawCbs_t * p;
p = dmaCB2adr(b);
static void dmaTickCb(int b, int pos)
{
- dmaCbs_t * p;
+ rawCbs_t * p;
p = dmaCB2adr(b);
static void dmaGpioOffCb(int b, int pos)
{
- dmaCbs_t * p;
+ rawCbs_t * p;
p = dmaCB2adr(b);
static void dmaReadLevelsCb(int b, int pos)
{
- dmaCbs_t * p;
+ rawCbs_t * p;
p = dmaCB2adr(b);
static void dmaDelayCb(int b)
{
- dmaCbs_t * p;
+ rawCbs_t * p;
p = dmaCB2adr(b);
{
int b, pulse, level, cycle;
- dmaCbs_t * p;
+ rawCbs_t * p;
/* set up the DMA control blocks */
if (err != (MAX_EMITS*sizeof(gpioReport_t)))
{
- DBG(0, "fd=%d err=%d errno=%d",
- gpioNotify[n].fd, err, errno);
- if (err < 0) DBG(0, "%s", strerror(errno));
- if ((err != EAGAIN) && (err != EWOULDBLOCK))
+ if (err < 0)
{
- /* serious error, no point continuing */
- gpioNotify[n].bits = 0;
- gpioNotify[n].state = PI_NOTIFY_CLOSING;
- intNotifyBits();
- break;
+ if ((errno != EAGAIN) && (errno != EWOULDBLOCK))
+ {
+ /* serious error, no point continuing */
+
+ DBG(0, "fd=%d err=%d errno=%d",
+ gpioNotify[n].fd, err, errno);
+
+ DBG(0, "%s", strerror(errno));
+
+ gpioNotify[n].bits = 0;
+ gpioNotify[n].state = PI_NOTIFY_CLOSING;
+ intNotifyBits();
+ break;
+ }
}
}
if (err != (emit*sizeof(gpioReport_t)))
{
- DBG(0, "fd=%d err=%d errno=%d",
- gpioNotify[n].fd, err, errno);
- if (err < 0) DBG(0, "%s", strerror(errno));
- if ((err != EAGAIN) && (err != EWOULDBLOCK))
+ if (err < 0)
{
- /* serious error, no point continuing */
- gpioNotify[n].bits = 0;
- gpioNotify[n].state = PI_NOTIFY_CLOSING;
- intNotifyBits();
- break;
+ if ((errno != EAGAIN) && (errno != EWOULDBLOCK))
+ {
+ DBG(0, "fd=%d err=%d errno=%d",
+ gpioNotify[n].fd, err, errno);
+
+ DBG(0, "%s", strerror(errno));
+
+ /* serious error, no point continuing */
+ gpioNotify[n].bits = 0;
+ gpioNotify[n].state = PI_NOTIFY_CLOSING;
+ intNotifyBits();
+ break;
+ }
}
}
if (changedBits & scriptBits)
{
- for (n=0; n<PI_SCRIPT_SLOTS; n++)
+ for (n=0; n<PI_MAX_SCRIPTS; n++)
{
if ((gpioScript[n].state == PI_SCRIPT_IN_USE) &&
(gpioScript[n].run_state == PI_SCRIPT_WAITING) &&
gpioScript_t *s;
gpioExtent_t oExt[3];
char buf[CMD_BUF_SIZE];
- gpioInstr_t instr;
- int p1, p2;
+ cmdInstr_t instr;
+ int p1, p2, p1o, p2o, *t1, *t2;
int PC, A, F, SP;
int S[PI_SCRIPT_STACK_SIZE];
while ((s->request == PI_SCRIPT_RUN ) &&
(s->run_state == PI_SCRIPT_RUNNING))
{
- instr = s->instr[PC];
+ instr = s->script.instr[PC];
+
+ p1o = instr.p[1];
+ p2o = instr.p[2];
- p1 = instr.p[1];
- p2 = instr.p[2];
+ if (instr.opt[0] == CMD_VAR) instr.p[1] = s->script.var[p1o];
+ else if (instr.opt[0] == CMD_PAR) instr.p[1] = s->script.par[p1o];
+
+ if (instr.opt[1] == CMD_VAR) instr.p[2] = s->script.var[p2o];
+ else if (instr.opt[1] == CMD_PAR) instr.p[2] = s->script.par[p2o];
if (instr.p[0] < 100)
{
oExt[0].ptr = buf;
oExt[0].size = CMD_BUF_SIZE-1;
- if (instr.opt[0] == CMD_PARAM)
- {
- instr.p[1] = s->param[p1];
- }
- else if (instr.opt[0] == CMD_VAR)
- {
- instr.p[1] = s->var[p1];
- }
-
- if (instr.opt[1] == CMD_PARAM)
- {
- instr.p[2] = s->param[p2];
- }
- else if (instr.opt[1] == CMD_VAR)
- {
- instr.p[2] = s->var[p2];
- }
-
A = myDoCommand(instr.p, oExt);
F = A;
}
else
{
+ p1 = instr.p[1];
+ p2 = instr.p[2];
+
switch (instr.p[0])
{
- case PI_CMD_ADDI: A+=p1; F=A; PC++; break;
-
- case PI_CMD_ADDV: A+=s->var[p1]; F=A; PC++; break;
-
- case PI_CMD_ANDI: A&=p1; F=A; PC++; break;
+ case PI_CMD_ADD: A+=p1; F=A; PC++; break;
- case PI_CMD_ANDV: A&=s->var[p1]; F=A; PC++; break;
+ case PI_CMD_AND: A&=p1; F=A; PC++; break;
- case PI_CMD_CALL: scrPush(s, S, &SP, PC+1); PC = p1; break;
+ case PI_CMD_CALL: scrPush(s, &SP, S, PC+1); PC = p1; break;
- case PI_CMD_CMPI: F=A-p1; PC++; break;
+ case PI_CMD_CMP: F=A-p1; PC++; break;
- case PI_CMD_CMPV: F=A-s->var[p1]; PC++; break;
-
- case PI_CMD_DCRA: --A; F=A; PC++; break;
-
- case PI_CMD_DCRV: --s->var[p1]; F=s->var[p1]; PC++; break;
-
- case PI_CMD_HALT: s->run_state = PI_SCRIPT_HALTED; break;
+ case PI_CMD_DCR:
+ if (instr.opt[0] == CMD_PAR)
+ {--s->script.par[p1o]; F=s->script.par[p1o];}
+ else
+ {--s->script.var[p1o]; F=s->script.var[p1o];}
+ PC++;
+ break;
- case PI_CMD_INRA: ++A; F=A; PC++; break;
+ case PI_CMD_DCRA: --A; F=A; PC++; break;
- case PI_CMD_INRV: ++s->var[p1]; F=s->var[p1]; PC++; break;
+ case PI_CMD_DIV: A/=p1; F=A; PC++; break;
- case PI_CMD_JM: if (F<0) PC=p1; else PC++; break;
+ case PI_CMD_HALT: s->run_state = PI_SCRIPT_HALTED; break;
- case PI_CMD_JMP: PC=p1; break;
+ case PI_CMD_INR:
+ if (instr.opt[0] == CMD_PAR)
+ {++s->script.par[p1o]; F=s->script.par[p1o];}
+ else
+ {++s->script.var[p1o]; F=s->script.var[p1o];}
+ PC++;
+ break;
- case PI_CMD_JNZ: if (F) PC=p1; else PC++; break;
+ case PI_CMD_INRA: ++A; F=A; PC++; break;
- case PI_CMD_JP: if (F>=0) PC=p1; else PC++; break;
+ case PI_CMD_JM: if (F<0) PC=p1; else PC++; break;
- case PI_CMD_JZ: if (!F) PC=p1; else PC++; break;
+ case PI_CMD_JMP: PC=p1; break;
- case PI_CMD_LABEL: PC++; break;
+ case PI_CMD_JNZ: if (F) PC=p1; else PC++; break;
- case PI_CMD_LDAI: A=p1; PC++; break;
+ case PI_CMD_JP: if (F>=0) PC=p1; else PC++; break;
- case PI_CMD_LDAP: A=s->param[p1]; PC++; break;
+ case PI_CMD_JZ: if (!F) PC=p1; else PC++; break;
- case PI_CMD_LDAV: A=s->var[p1]; PC++; break;
+ case PI_CMD_LD:
+ if (instr.opt[0] == CMD_PAR) s->script.par[p1o]=p2;
+ else s->script.var[p1o]=p2;
+ PC++;
+ break;
- case PI_CMD_LDPA: s->param[p1]=A; PC++; break;
+ case PI_CMD_LDA: A=p1; PC++; break;
- case PI_CMD_LDVA: s->var[p1]=A; PC++; break;
+ case PI_CMD_MLT: A*=p1; F=A; PC++; break;
- case PI_CMD_LDVI: s->var[p1] = p2; PC++; break;
+ case PI_CMD_MOD: A%=p1; F=A; PC++; break;
- case PI_CMD_LDVV: s->var[p1]=s->var[p2]; PC++; break;
+ case PI_CMD_OR: A|=p1; F=A; PC++; break;
- case PI_CMD_ORI: A|=p1; F=A; PC++; break;
+ case PI_CMD_POP:
+ if (instr.opt[0] == CMD_PAR)
+ s->script.par[p1o]=scrPop(s, &SP, S);
+ else
+ s->script.var[p1o]=scrPop(s, &SP, S);
+ PC++;
+ break;
- case PI_CMD_ORV: A|=s->var[p1]; F=A; PC++; break;
+ case PI_CMD_POPA: A=scrPop(s, &SP, S); PC++; break;
- case PI_CMD_POPA: A=scrPop(s, S, &SP); PC++; break;
+ case PI_CMD_PUSH:
+ if (instr.opt[0] == CMD_PAR)
+ scrPush(s, &SP, S, s->script.par[p1o]);
+ else
+ scrPush(s, &SP, S, s->script.var[p1o]);
+ PC++;
+ break;
- case PI_CMD_POPV: s->var[p1]=scrPop(s, S, &SP); PC++; break;
+ case PI_CMD_PUSHA: scrPush(s, &SP, S, A); PC++; break;
- case PI_CMD_PUSHA: scrPush(s, S, &SP, A); PC++; break;
+ case PI_CMD_RET: PC=scrPop(s, &SP, S); break;
- case PI_CMD_PUSHV: scrPush(s, S, &SP, s->var[p1]); PC++; break;
+ case PI_CMD_RL:
+ if (instr.opt[0] == CMD_PAR)
+ {s->script.par[p1o]<<=p2; F=s->script.par[p1o];}
+ else
+ {s->script.var[p1o]<<=p2; F=s->script.var[p1o];}
+ PC++;
+ break;
- case PI_CMD_RET: PC=scrPop(s, S, &SP); break;
+ case PI_CMD_RLA: A<<=p1; F=A; PC++; break;
- case PI_CMD_RAL: A<<=p1; F=A; PC++; break;
+ case PI_CMD_RR:
+ if (instr.opt[0] == CMD_PAR)
+ {s->script.par[p1o]>>=p2; F=s->script.par[p1o];}
+ else
+ {s->script.var[p1o]>>=p2; F=s->script.var[p1o];}
+ PC++;
+ break;
- case PI_CMD_RAR: A>>=p1; F=A; PC++; break;
+ case PI_CMD_RRA: A>>=p1; F=A; PC++; break;
- case PI_CMD_SUBI: A-=p1; F=A; PC++; break;
+ case PI_CMD_STA:
+ if (instr.opt[0] == CMD_PAR) s->script.par[p1o]=A;
+ else s->script.var[p1o]=A;
+ PC++;
+ break;
- case PI_CMD_SUBV: A-=s->var[p1]; F=A; PC++; break;
+ case PI_CMD_SUB: A-=p1; F=A; PC++; break;
- case PI_CMD_SWAPA: scrSwap(&s->var[p1], &A); PC++; break;
+ case PI_CMD_X:
+ if (instr.opt[0] == CMD_PAR) t1 = &s->script.par[p1o];
+ else t1 = &s->script.var[p1o];
- case PI_CMD_SWAPV: scrSwap(&s->var[p1], &s->var[p2]);PC++; break;
+ if (instr.opt[1] == CMD_PAR) t2 = &s->script.par[p2o];
+ else t2 = &s->script.var[p2o];
- case PI_CMD_SYS: A=scrSys((char*)p1, A); F=A; PC++; break;
+ scrSwap(t1, t2);
+ PC++;
+ break;
- case PI_CMD_WAITI: A=scrWait(s, p1); F=A; PC++; break;
+ case PI_CMD_XA:
+ if (instr.opt[0] == CMD_PAR)
+ scrSwap(&s->script.par[p1o], &A);
+ else
+ scrSwap(&s->script.var[p1o], &A);
+ PC++;
+ break;
- case PI_CMD_WAITV: A=scrWait(s, s->var[p1]); F=A; PC++; break;
+ case PI_CMD_SYS: A=scrSys((char*)p1, A); F=A; PC++; break;
- case PI_CMD_XORI: A^=p1; F=A; PC++; break;
+ case PI_CMD_WAIT: A=scrWait(s, p1); F=A; PC++; break;
- case PI_CMD_XORV: A^=s->var[p1]; F=A; PC++; break;
+ case PI_CMD_XOR: A^=p1; F=A; PC++; break;
}
}
- if (PC >= s->instrs) s->run_state = PI_SCRIPT_HALTED;
+ if (PC >= s->script.instrs) s->run_state = PI_SCRIPT_HALTED;
}
uint32_t p[10];
void *v[10];
gpioExtent_t oExt[3];
- gpioCtlParse_t ctl;
+ cmdCtlParse_t ctl;
char *pp;
uint32_t *param;
- ctl.flags = 0;
-
myCreatePipe(PI_INPFIFO, 0662);
if ((inpFifo = fopen(PI_INPFIFO, "r+")) == NULL)
{
fprintf(outFifo, "%d", res);
param = oExt[0].ptr;
- for (i=0; i<MAX_SCRIPT_PARAMS; i++)
+ for (i=0; i<PI_MAX_SCRIPT_PARAMS; i++)
{
fprintf(outFifo, " %d", param[i]);
}
if (res >= 0)
{
- write(sock, oExt[0].ptr, sizeof(uint32_t)*MAX_SCRIPT_PARAMS);
+ write(sock, oExt[0].ptr, sizeof(uint32_t)*PI_MAX_SCRIPT_PARAMS);
}
break;
/* ----------------------------------------------------------------------- */
-uint32_t waveGetRawOut(int pos)
+uint32_t rawWaveGetOut(int pos)
{
int page, slot;
- if ((pos >= 0) && (pos < NUM_OOL))
+ if ((pos >= 0) && (pos < NUM_WAVE_OOL))
{
waveOOLPageSlot(pos, &page, &slot);
return (dmaOVirt[page]->OOL[slot]);
{
int page, slot;
- if ((pos >= 0) && (pos < NUM_OOL))
+ if ((pos >= 0) && (pos < NUM_WAVE_OOL))
{
waveOOLPageSlot(pos, &page, &slot);
dmaOVirt[page]->OOL[slot] = value;
/* ----------------------------------------------------------------------- */
-uint32_t waveGetRawIn(int pos)
+uint32_t rawWaveGetIn(int pos)
{
int page, slot;
- if ((pos >= 0) && (pos < NUM_OOL))
+ if ((pos >= 0) && (pos < NUM_WAVE_OOL))
{
- waveOOLPageSlot((NUM_OOL-1)-pos, &page, &slot);
+ waveOOLPageSlot((NUM_WAVE_OOL-1)-pos, &page, &slot);
return (dmaOVirt[page]->OOL[slot]);
}
/* ----------------------------------------------------------------------- */
-void waveSetRawIn(int pos, uint32_t value)
+void rawWaveSetIn(int pos, uint32_t value)
{
int page, slot;
- if ((pos >= 0) && (pos < NUM_OOL))
+ if ((pos >= 0) && (pos < NUM_WAVE_OOL))
{
- waveOOLPageSlot((NUM_OOL-1)-pos, &page, &slot);
+ waveOOLPageSlot((NUM_WAVE_OOL-1)-pos, &page, &slot);
dmaOVirt[page]->OOL[slot] = value;
}
}
/* ----------------------------------------------------------------------- */
-void gpioDumpWave(void)
+void rawDumpWave(void)
{
int i;
/* ----------------------------------------------------------------------- */
-void gpioDumpScript(int s)
+void rawDumpScript(int s)
{
int i;
- for (i=0; i<MAX_SCRIPT_PARAMS; i++)
+ for (i=0; i<PI_MAX_SCRIPT_PARAMS; i++)
{
- fprintf(stderr, "p%d=%d ", i, gpioScript[s].param[i]);
+ fprintf(stderr, "p%d=%d ", i, gpioScript[s].script.par[i]);
}
fprintf(stderr, "\n");
- for (i=0; i<MAX_SCRIPT_VARS; i++)
+ for (i=0; i<PI_MAX_SCRIPT_VARS; i++)
{
- fprintf(stderr, "v%d=%d ", i, gpioScript[s].var[i]);
+ fprintf(stderr, "v%d=%d ", i, gpioScript[s].script.var[i]);
}
fprintf(stderr, "\n");
- for (i=0; i<gpioScript[s].instrs; i++)
+ for (i=0; i<gpioScript[s].script.instrs; i++)
{
fprintf(stderr, "c%d=[%d, %d(%d), %d(%d)]\n",
- i, gpioScript[s].instr[i].p[0],
- gpioScript[s].instr[i].p[1], gpioScript[s].instr[i].opt[0],
- gpioScript[s].instr[i].p[2], gpioScript[s].instr[i].opt[1]);
+ i, gpioScript[s].script.instr[i].p[0],
+ gpioScript[s].script.instr[i].p[1], gpioScript[s].script.instr[i].opt[0],
+ gpioScript[s].script.instr[i].p[2], gpioScript[s].script.instr[i].opt[1]);
}
}
/* ----------------------------------------------------------------------- */
-int gpioWaveGetMicros(void)
+int gpioWaveClear(void)
{
DBG(DBG_USER, "");
CHECK_INITED;
- return wfStats.micros;
-}
+ wfc[0] = 0;
+ wfc[1] = 0;
+ wfc[2] = 0;
+ wfcur = 0;
-/* ----------------------------------------------------------------------- */
+ wfStats.micros = 0;
+ wfStats.pulses = 0;
+ wfStats.cbs = 0;
-int gpioWaveGetHighMicros(void)
-{
- DBG(DBG_USER, "");
+ waveOutBotCB = 0;
+ waveOutTopCB = NUM_WAVE_CBS;
+ waveOutBotOOL = 0;
+ waveOutTopOOL = NUM_WAVE_OOL;
- CHECK_INITED;
+ waveOutCount = 0;
- return wfStats.highMicros;
+ return 0;
}
-
/* ----------------------------------------------------------------------- */
-int gpioWaveGetMaxMicros(void)
+int gpioWaveAddNew(void)
{
DBG(DBG_USER, "");
CHECK_INITED;
- return wfStats.maxMicros;
-}
-
-
-/* ----------------------------------------------------------------------- */
+ wfc[0] = 0;
+ wfc[1] = 0;
+ wfc[2] = 0;
-int gpioWaveGetPulses(void)
-{
- DBG(DBG_USER, "");
+ wfcur = 0;
- CHECK_INITED;
+ wfStats.micros = 0;
+ wfStats.pulses = 0;
+ wfStats.cbs = 0;
- return wfStats.pulses;
+ return 0;
}
-
/* ----------------------------------------------------------------------- */
-int gpioWaveGetHighPulses(void)
+int gpioWaveAddGeneric(unsigned numPulses, gpioPulse_t *pulses)
{
- DBG(DBG_USER, "");
+ int p;
+
+ DBG(DBG_USER, "numPulses=%u pulses=%08X", numPulses, (uint32_t)pulses);
CHECK_INITED;
- return wfStats.highPulses;
-}
+ if (numPulses > PI_WAVE_MAX_PULSES)
+ SOFT_ERROR(PI_TOO_MANY_PULSES, "bad number of pulses (%d)", numPulses);
+
+ for (p=0; p<numPulses; p++)
+ {
+ wf[2][p].gpioOff = pulses[p].gpioOff;
+ wf[2][p].gpioOn = pulses[p].gpioOn;
+ wf[2][p].usDelay = pulses[p].usDelay;
+ wf[2][p].flags = 0;
+ }
+ return waveMerge(numPulses, wf[2]);
+}
/* ----------------------------------------------------------------------- */
-int gpioWaveGetMaxPulses(void)
+int gpioWaveAddSerial(unsigned gpio,
+ unsigned baud,
+ unsigned offset,
+ unsigned numChar,
+ char *str)
{
- DBG(DBG_USER, "");
+ int i, b, p, lev, c, v;
- CHECK_INITED;
+ unsigned bitDelay[10];
- return wfStats.maxPulses;
-}
+ 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;
-int gpioWaveGetCbs(void)
-{
- DBG(DBG_USER, "");
+ if (gpio > PI_MAX_USER_GPIO)
+ SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
- CHECK_INITED;
+ if ((baud < PI_WAVE_MIN_BAUD) || (baud > PI_WAVE_MAX_BAUD))
+ SOFT_ERROR(PI_BAD_WAVE_BAUD,
+ "gpio %d, bad baud rate (%d)", gpio, baud);
- return wfStats.cbs;
-}
+ if (numChar > PI_WAVE_MAX_CHARS)
+ 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);
-/* ----------------------------------------------------------------------- */
-
-int gpioWaveGetHighCbs(void)
-{
- DBG(DBG_USER, "");
-
- CHECK_INITED;
-
- return wfStats.highCbs;
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-int gpioWaveGetMaxCbs(void)
-{
- DBG(DBG_USER, "");
-
- CHECK_INITED;
-
- return wfStats.maxCbs;
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-int gpioWaveClear(void)
-{
- DBG(DBG_USER, "");
-
- CHECK_INITED;
-
- wfc[0] = 0;
- wfc[1] = 0;
- wfc[2] = 0;
-
- wfcur = 0;
-
- wfStats.micros = 0;
- wfStats.pulses = 0;
- wfStats.cbs = 0;
-
- return 0;
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-int gpioWaveAddGeneric(unsigned numPulses, gpioPulse_t *pulses)
-{
- int p;
-
- DBG(DBG_USER, "numPulses=%u pulses=%08X", numPulses, (uint32_t)pulses);
-
- CHECK_INITED;
-
- if (numPulses > PI_WAVE_MAX_PULSES)
- SOFT_ERROR(PI_TOO_MANY_PULSES, "bad number of pulses (%d)", numPulses);
-
- for (p=0; p<numPulses; p++)
- {
- wf[2][p].gpioOff = pulses[p].gpioOff;
- wf[2][p].gpioOn = pulses[p].gpioOn;
- wf[2][p].usDelay = pulses[p].usDelay;
- wf[2][p].flags = 0;
- }
-
- return waveMerge(numPulses, wf[2]);
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-int gpioWaveAddSerial(unsigned gpio,
- unsigned baud,
- unsigned offset,
- unsigned numChar,
- char *str)
-{
- int i, b, p, lev, c, v;
-
- unsigned bitDelay[10];
-
- 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)
- SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
-
- if ((baud < PI_WAVE_MIN_BAUD) || (baud > PI_WAVE_MAX_BAUD))
- SOFT_ERROR(PI_BAD_WAVE_BAUD,
- "gpio %d, bad baud rate (%d)", gpio, baud);
-
- if (numChar > PI_WAVE_MAX_CHARS)
- 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);
/* ----------------------------------------------------------------------- */
-int gpioWaveAddSPI(
- gpioSPI_t *spi,
+int rawWaveAddSPI(
+ rawSPI_t *spi,
unsigned offset,
unsigned ss,
uint8_t *tx_bits,
return waveMerge(p, wf[2]);
}
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveCreate(void)
+{
+ int cb;
+
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ if (wfc[wfcur] == 0) return PI_EMPTY_WAVEFORM;
+
+ if (waveOutCount < PI_MAX_WAVES)
+ {
+ waveInfo[waveOutCount].botCB = waveOutBotCB;
+ waveInfo[waveOutCount].botOOL = waveOutBotOOL;
+ waveInfo[waveOutCount].topOOL = waveOutTopOOL;
+
+ if ((cb = wave2Cbs(PI_WAVE_MODE_ONE_SHOT)) < 0) return cb;
+
+ waveInfo[waveOutCount].topCB = waveOutBotCB-1;
+
+ gpioWaveAddNew();
+
+ return waveOutCount++;
+ }
+
+ return PI_NO_WAVEFORM_ID;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveDelete(unsigned wave_id)
+{
+ DBG(DBG_USER, "wave id=%d", wave_id);
+
+ CHECK_INITED;
+
+ if (wave_id >= waveOutCount)
+ SOFT_ERROR(PI_BAD_WAVE_ID, "bad wave id (%d)", wave_id);
+
+ waveOutBotCB = waveInfo[wave_id].botCB;
+ waveOutBotOOL = waveInfo[wave_id].botOOL;
+ waveOutTopOOL = waveInfo[wave_id].topOOL;
+
+ waveOutCount = wave_id;
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveTxStart(unsigned mode)
+{
+ /* This function is deprecated and will be removed. */
+
+ static int secondaryClockInited = 0;
+
+ int cb, i;
+
+ DBG(DBG_USER, "mode=%d", mode);
+
+ CHECK_INITED;
+
+ if (mode > PI_WAVE_MODE_REPEAT)
+ SOFT_ERROR(PI_BAD_WAVE_MODE, "bad wave mode (%d)", mode);
+
+ if (wfc[wfcur] == 0) return 0;
+
+ if (!secondaryClockInited)
+ {
+ initClock(0); /* initialise secondary clock */
+ secondaryClockInited = 1;
+ }
+
+ dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
+
+ dmaOut[DMA_CONBLK_AD] = 0;
+
+ waveOutBotCB = 0;
+ waveOutTopCB = NUM_WAVE_CBS;
+ waveOutBotOOL = 0;
+ waveOutTopOOL = NUM_WAVE_OOL;
+
+ waveOutCount = 0;
+
+ cb = wave2Cbs(mode);
+
+ if (gpioCfg.dbgLevel >= DBG_SLOW_TICK)
+ {
+ fprintf(stderr, "*** OUTPUT DMA CONTROL BLOCKS ***\n");
+ for (i=0; i<cb; i++) waveCbOPrint(i);
+ }
+
+ initDMAgo((uint32_t *)dmaOut, (uint32_t)dmaOPhys[0]);
+
+ return cb;
+
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveTxSend(unsigned wave_id, unsigned mode)
+{
+ rawCbs_t *p=NULL;
+
+ static int secondaryClockInited = 0;
+
+ DBG(DBG_USER, "wave_id=%d mode=%d", wave_id, mode);
+
+ CHECK_INITED;
+
+ if (wave_id >= waveOutCount)
+ SOFT_ERROR(PI_BAD_WAVE_ID, "bad wave id (%d)", wave_id);
+
+ if (mode > PI_WAVE_MODE_REPEAT)
+ SOFT_ERROR(PI_BAD_WAVE_MODE, "bad wave mode (%d)", mode);
+
+ if (!secondaryClockInited)
+ {
+ initClock(0); /* initialise secondary clock */
+ secondaryClockInited = 1;
+ }
+
+ p = rawWaveCBAdr(waveInfo[wave_id].topCB);
+
+ if (mode == PI_WAVE_MODE_ONE_SHOT) p->next = 0;
+ else p->next = waveCbPOadr(waveInfo[wave_id].botCB+1) | DMA_BUS_ADR;
+
+ dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
+
+ dmaOut[DMA_CONBLK_AD] = 0;
+
+ initDMAgo((uint32_t *)dmaOut, waveCbPOadr(waveInfo[wave_id].botCB));
+
+ /* for compatability with the deprecated gpioWaveTxStart return the
+ number of cbs
+ */
+ return (waveInfo[wave_id].topCB - waveInfo[wave_id].botCB) + 1;
+}
+
+/*-------------------------------------------------------------------------*/
+
+int gpioWaveTxBusy(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ if (dmaOut[DMA_CONBLK_AD])
+ return 1;
+ else
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveTxStop(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
+
+ dmaOut[DMA_CONBLK_AD] = 0;
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveGetMicros(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ return wfStats.micros;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveGetHighMicros(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ return wfStats.highMicros;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveGetMaxMicros(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ return wfStats.maxMicros;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveGetPulses(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ return wfStats.pulses;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveGetHighPulses(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ return wfStats.highPulses;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveGetMaxPulses(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ return wfStats.maxPulses;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveGetCbs(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ return wfStats.cbs;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveGetHighCbs(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ return wfStats.highCbs;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int gpioWaveGetMaxCbs(void)
+{
+ DBG(DBG_USER, "");
+
+ CHECK_INITED;
+
+ return wfStats.maxCbs;
+}
+
/*-------------------------------------------------------------------------*/
int gpioSerialReadOpen(unsigned gpio, unsigned baud)
if (bytes > bufSize) bytes = bufSize;
- memcpy(buf, p->buf+p->readPos, bytes);
+ if (buf) memcpy(buf, p->buf+p->readPos, bytes);
p->readPos += bytes;
}
-/*-------------------------------------------------------------------------*/
-
-int gpioWaveTxBusy(void)
-{
- DBG(DBG_USER, "");
-
- CHECK_INITED;
-
- if (dmaOut[DMA_CONBLK_AD])
- return 1;
- else
- return 0;
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-int gpioWaveTxStart(unsigned mode)
-{
- static int secondaryClockInited = 0;
-
- int cb, i;
-
- DBG(DBG_USER, "mode=%d", mode);
-
- CHECK_INITED;
-
- if (mode > PI_WAVE_MODE_REPEAT)
- SOFT_ERROR(PI_BAD_WAVE_MODE, "bad wave mode (%d)", mode);
-
- if (wfc[wfcur] == 0) return 0;
-
- if (!secondaryClockInited)
- {
- initClock(0); /* initialise secondary clock */
- secondaryClockInited = 1;
- }
-
- dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
-
- dmaOut[DMA_CONBLK_AD] = 0;
-
- cb = wave2Cbs(mode);
-
- if (gpioCfg.dbgLevel >= DBG_SLOW_TICK)
- {
- fprintf(stderr, "*** OUTPUT DMA CONTROL BLOCKS ***\n");
- for (i=0; i<cb; i++) waveCbOPrint(i);
- }
-
- initDMAgo((uint32_t *)dmaOut, (uint32_t)dmaOPhys[0]);
-
- return cb;
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-int gpioWaveTxStop(void)
-{
- DBG(DBG_USER, "");
-
- CHECK_INITED;
-
- dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
-
- dmaOut[DMA_CONBLK_AD] = 0;
-
- return 0;
-}
-
-
/* ----------------------------------------------------------------------- */
static int intGpioSetAlertFunc(
bits = 0;
- for (i=0; i<PI_SCRIPT_SLOTS; i++)
+ for (i=0; i<PI_MAX_SCRIPTS; i++)
{
if (gpioScript[i].state == PI_SCRIPT_IN_USE)
{
CHECK_INITED;
- if (handle > PI_NOTIFY_SLOTS)
+ if (handle >= PI_NOTIFY_SLOTS)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
if (gpioNotify[handle].state <= PI_NOTIFY_CLOSING)
CHECK_INITED;
- if (handle > PI_NOTIFY_SLOTS)
+ if (handle >= PI_NOTIFY_SLOTS)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
if (gpioNotify[handle].state <= PI_NOTIFY_CLOSING)
CHECK_INITED;
- if (handle > PI_NOTIFY_SLOTS)
+ if (handle >= PI_NOTIFY_SLOTS)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
if (gpioNotify[handle].state <= PI_NOTIFY_CLOSING)
slot = -1;
- for (i=0; i<PI_SCRIPT_SLOTS; i++)
+ for (i=0; i<PI_MAX_SCRIPTS; i++)
{
if (gpioScript[i].state == PI_SCRIPT_FREE)
{
s = &gpioScript[slot];
- status = myParseScript(script, s);
+ status = cmdParseScript(script, &s->script, 0);
if (status == 0)
{
}
else
{
- if (s->param) free(s->param);
- s->param = NULL;
+ if (s->script.par) free(s->script.par);
+ s->script.par = NULL;
gpioScript[slot].state = PI_SCRIPT_FREE;
}
/* ----------------------------------------------------------------------- */
-int gpioRunScript(int script_id, unsigned numParam, uint32_t *param)
+int gpioRunScript(unsigned script_id, unsigned numParam, uint32_t *param)
{
int status = 0;
CHECK_INITED;
- if (numParam > MAX_SCRIPT_PARAMS)
+ if (script_id >= PI_MAX_SCRIPTS)
+ SOFT_ERROR(PI_BAD_SCRIPT_ID, "bad script id(%d)", script_id);
+
+ if (numParam > PI_MAX_SCRIPT_PARAMS)
SOFT_ERROR(PI_TOO_MANY_PARAM, "bad number of parameters(%d)", numParam);
if (gpioScript[script_id].state == PI_SCRIPT_IN_USE)
{
if ((numParam > 0) && (param != 0))
{
- memcpy(gpioScript[script_id].param, param,
+ memcpy(gpioScript[script_id].script.par, param,
sizeof(uint32_t) * numParam);
}
return status;
}
- else return PI_BAD_SCRIPT_ID;
+ else
+ {
+ return PI_BAD_SCRIPT_ID;
+ }
}
/* ----------------------------------------------------------------------- */
-int gpioScriptStatus(int script_id, uint32_t *param)
+int gpioScriptStatus(unsigned script_id, uint32_t *param)
{
DBG(DBG_USER, "script_id=%d param=%08X", script_id, (uint32_t)param);
CHECK_INITED;
+ if (script_id >= PI_MAX_SCRIPTS)
+ SOFT_ERROR(PI_BAD_SCRIPT_ID, "bad script id(%d)", script_id);
+
if (gpioScript[script_id].state == PI_SCRIPT_IN_USE)
{
if (param != 0)
{
- memcpy(param, gpioScript[script_id].param,
- sizeof(uint32_t) * MAX_SCRIPT_PARAMS);
+ memcpy(param, gpioScript[script_id].script.par,
+ sizeof(uint32_t) * PI_MAX_SCRIPT_PARAMS);
}
return gpioScript[script_id].run_state;
/* ----------------------------------------------------------------------- */
-int gpioStopScript(int script_id)
+int gpioStopScript(unsigned script_id)
{
DBG(DBG_USER, "script_id=%d", script_id);
CHECK_INITED;
+ if (script_id >= PI_MAX_SCRIPTS)
+ SOFT_ERROR(PI_BAD_SCRIPT_ID, "bad script id(%d)", script_id);
+
if (gpioScript[script_id].state == PI_SCRIPT_IN_USE)
{
pthread_mutex_lock(&gpioScript[script_id].pthMutex);
/* ----------------------------------------------------------------------- */
-int gpioDeleteScript(int script_id)
+int gpioDeleteScript(unsigned script_id)
{
DBG(DBG_USER, "script_id=%d", script_id);
CHECK_INITED;
+ if (script_id >= PI_MAX_SCRIPTS)
+ SOFT_ERROR(PI_BAD_SCRIPT_ID, "bad script id(%d)", script_id);
+
if (gpioScript[script_id].state == PI_SCRIPT_IN_USE)
{
gpioScript[script_id].state = PI_SCRIPT_DYING;
gpioStopThread(gpioScript[script_id].pthIdp);
- if (gpioScript[script_id].param) free(gpioScript[script_id].param);
+ if (gpioScript[script_id].script.par) free(gpioScript[script_id].script.par);
- gpioScript[script_id].param = NULL;
+ gpioScript[script_id].script.par = NULL;
gpioScript[script_id].state = PI_SCRIPT_FREE;
start = systReg[SYST_CLO];
- if (micros < 101) while ((systReg[SYST_CLO] - start) <= micros) ;
+ if (micros <= MAX_DELAY) while ((systReg[SYST_CLO] - start) <= micros) ;
else gpioSleep(PI_TIME_RELATIVE, (micros/MILLION), (micros%MILLION));
*/
/*
-This version is for pigpio version 13
+This version is for pigpio version 14
*/
#ifndef PIGPIO_H
#include <stdint.h>
#include <pthread.h>
-#define PIGPIO_VERSION 13
+#define PIGPIO_VERSION 14
/*-------------------------------------------------------------------------*/
gpioNotifyPause Pause a gpio(s) changed notification.
gpioNotifyClose Close a gpio(s) changed notification.
-gpioWaveClear Initialises a new waveform.
+gpioWaveClear Deletes all waveforms.
+
+gpioWaveAddNew Starts a new waveform.
gpioWaveAddGeneric Adds a series of pulses to the waveform.
gpioWaveAddSerial Adds serial data to the waveform.
-gpioWaveTxStart Transmits the waveform.
+gpioWaveCreate Creates a waveform from added data.
+gpioWaveDelete Deletes one or more waveforms.
+
+gpioWaveTxStart Creates/transmits a waveform (DEPRECATED).
+
+gpioWaveTxSend Transmits a waveform.
gpioWaveTxBusy Checks to see if the waveform has ended.
gpioWaveTxStop Aborts the current waveform.
-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.
gpioWaveGetMaxMicros Absolute maximum allowed micros.
gpioWaveGetHighCbs Length of longest waveform so far.
gpioWaveGetMaxCbs Absolute maximum allowed cbs.
+gpioSerialReadOpen Opens a gpio for reading serial data.
+gpioSerialRead Reads serial data from a gpio.
+gpioSerialReadClose Closes a gpio for reading serial data.
+
gpioTrigger Send a trigger pulse to a gpio.
gpioSetWatchdog Set a watchdog on a gpio.
int clk_pol; /* clock off state */
int clk_pha; /* clock phase */
int clk_us; /* clock micros */
-} gpioSPI_t;
+} rawSPI_t;
+
+typedef struct { /* linux/arch/arm/mach-bcm2708/include/mach/dma.h */
+ unsigned long info;
+ unsigned long src;
+ unsigned long dst;
+ unsigned long length;
+ unsigned long stride;
+ unsigned long next;
+ unsigned long pad[2];
+} rawCbs_t;
typedef void (*gpioAlertFunc_t) (int gpio,
int level,
/*-------------------------------------------------------------------------*/
int gpioWaveClear(void);
/*-------------------------------------------------------------------------*/
-/* This function initialises a new waveform.
+/* This function clears all waveforms and any data added by calls to the
+ gpioWaveAdd* functions.
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).
+/*-------------------------------------------------------------------------*/
+int gpioWaveAddNew(void);
+/*-------------------------------------------------------------------------*/
+/* This function starts a new empty waveform. You wouldn't normally need
+ to call this function as it is automatically called after a waveform is
+ created with the gpioWaveCreate function.
- When a waveform is started each pulse is executed in order with the
- specified delay between the pulse and the next.
+ Returns 0 if OK.
*/
+
/*-------------------------------------------------------------------------*/
int gpioWaveAddGeneric(unsigned numPulses, gpioPulse_t * pulses);
/*-------------------------------------------------------------------------*/
NOTES:
- The pulses are interleaved in time order within the existing 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
#define PI_WAVE_MAX_MICROS (30 * 60 * 1000000) /* half an hour */
+#define PI_MAX_WAVES 100
+
+
+
/*-------------------------------------------------------------------------*/
-int gpioWaveTxStart(unsigned mode);
+int gpioWaveCreate(void);
/*-------------------------------------------------------------------------*/
-/* This function transmits the current waveform. The mode determines
- whether the waveform is sent once or cycles endlessly.
+/* This function creates a waveform from the data provided by the prior
+ calls to the gpioWaveAdd* functions. Upon success a positive wave id
+ is returned.
- Returns the number of DMA control blocks in the waveform if OK,
- otherwise PI_BAD_WAVE_MODE.
-*/
+ The data provided by the gpioWaveAdd* functions is consumed by this
+ function.
-#define PI_WAVE_MODE_ONE_SHOT 0
-#define PI_WAVE_MODE_REPEAT 1
+ As many waveforms may be created as there is space available. The
+ wave id is passed to gpioWaveTxSend to specify the waveform to transmit.
+ Normal usage would be
+ Step 1. gpioWaveClear to clear all waveforms and added data.
-/*-------------------------------------------------------------------------*/
-int gpioWaveTxBusy(void);
-/*-------------------------------------------------------------------------*/
-/* This function checks to see if a waveform is currently being
- transmitted.
+ Step 2. gpioWaveAdd* calls to supply the waveform data.
- Returns 1 if a waveform is currently being transmitted, otherwise 0.
-*/
+ Step 3. gpioWaveCreate to create the waveform and get a unique id
+ Repeat steps 2 and 3 as needed.
+ Step 4. gpioWaveTxSend with the id of the waveform to transmit.
-/*-------------------------------------------------------------------------*/
-int gpioWaveTxStop(void);
-/*-------------------------------------------------------------------------*/
-/* This function aborts the transmission of the current waveform.
+ A waveform comprises one of more pulses. Each pulse consists of a
+ gpioPulse_t structure.
- Returns 0 if OK.
+ typedef struct
+ {
+ uint32_t gpioOn;
+ uint32_t gpioOff;
+ uint32_t usDelay;
+ } gpioPulse_t;
- NOTES:
+ 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.
- This function is intended to stop a waveform started with the repeat mode.
+ 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.
+
+ Returns the new waveform id if OK, otherwise PI_EMPTY_WAVEFORM,
+ PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
*/
+/*-------------------------------------------------------------------------*/
+int gpioWaveDelete(unsigned wave_id);
+/*-------------------------------------------------------------------------*/
+/* This function deletes all created waveforms with ids greater than or
+ equal to wave_id.
+
+ Wave ids are allocated in order, 0, 1, 2, etc.
+
+ Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
+*/
+
/*-------------------------------------------------------------------------*/
-int gpioSerialReadOpen(unsigned user_gpio, unsigned baud);
+int gpioWaveTxStart(unsigned mode); /* DEPRECATED */
/*-------------------------------------------------------------------------*/
-/* This function opens a gpio for reading serial data.
+/* This function creates and then transmits a waveform. The mode
+ determines whether the waveform is sent once or cycles endlessly.
- Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD,
- or PI_GPIO_IN_USE.
+ This function is deprecated and should no longer be used. Use
+ gpioWaveCreate/gpioWaveTxSend instead.
- The serial data is returned in a cyclic buffer and is read using
- gpioSerialRead().
+ Returns the number of DMA control blocks in the waveform if OK,
+ otherwise PI_BAD_WAVE_MODE.
+*/
- It is the caller's responsibility to read data from the cyclic buffer
- in a timely fashion.
+/*-------------------------------------------------------------------------*/
+int gpioWaveTxSend(unsigned wave_id, unsigned mode);
+/*-------------------------------------------------------------------------*/
+/* This function transmits the waveform with id wave_id. The mode
+ determines whether the waveform is sent once or cycles endlessly.
+
+ Returns the number of DMA control blocks in the waveform if OK,
+ otherwise PI_BAD_WAVE_ID, or PI_BAD_WAVE_MODE.
*/
+#define PI_WAVE_MODE_ONE_SHOT 0
+#define PI_WAVE_MODE_REPEAT 1
+
/*-------------------------------------------------------------------------*/
-int gpioSerialRead(unsigned user_gpio, void *buf, size_t bufSize);
+int gpioWaveTxBusy(void);
/*-------------------------------------------------------------------------*/
-/* This function copies up to bufSize bytes of data read from the
- serial cyclic buffer to the buffer starting at buf.
+/* This function checks to see if a waveform is currently being
+ transmitted.
- Returns the number of bytes copied if OK, otherwise PI_BAD_USER_GPIO
- or PI_NOT_SERIAL_GPIO.
+ Returns 1 if a waveform is currently being transmitted, otherwise 0.
*/
/*-------------------------------------------------------------------------*/
-int gpioSerialReadClose(unsigned user_gpio);
+int gpioWaveTxStop(void);
/*-------------------------------------------------------------------------*/
-/* This function closes a gpio for reading serial data.
+/* This function aborts the transmission of the current waveform.
- Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SERIAL_GPIO.
+ Returns 0 if OK.
+
+ NOTES:
+
+ This function is intended to stop a waveform started in repeat mode.
*/
+/*-------------------------------------------------------------------------*/
+int gpioSerialReadOpen(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 gpioSerialRead(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 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.
+*/
+
+
+
/*-------------------------------------------------------------------------*/
int gpioTrigger(unsigned user_gpio, unsigned pulseLen, unsigned level);
/*-------------------------------------------------------------------------*/
or PI_BAD_PULSELEN.
*/
-#define PI_MAX_PULSELEN 100
+#define PI_MAX_PULSELEN 50
/*-------------------------------------------------------------------------*/
otherwise PI_BAD_SCRIPT.
*/
-#define MAX_SCRIPT_LABELS 50
-#define MAX_SCRIPT_VARS 150
-#define MAX_SCRIPT_PARAMS 10
+#define PI_MAX_SCRIPTS 32
+
+#define PI_MAX_SCRIPT_TAGS 50
+#define PI_MAX_SCRIPT_VARS 150
+#define PI_MAX_SCRIPT_PARAMS 10
/* ----------------------------------------------------------------------- */
-int gpioRunScript(int script_id, unsigned numParam, uint32_t *param);
+int gpioRunScript(unsigned script_id, unsigned numParam, uint32_t *param);
/* ----------------------------------------------------------------------- */
/* This function runs a stored script.
/* ----------------------------------------------------------------------- */
-int gpioScriptStatus(int script_id, uint32_t *param);
+int gpioScriptStatus(unsigned script_id, uint32_t *param);
/* ----------------------------------------------------------------------- */
/* This function returns the run status of a stored script as well as
the current values of parameters 0 to 9.
/* ----------------------------------------------------------------------- */
-int gpioStopScript(int script_id);
+int gpioStopScript(unsigned script_id);
/* ----------------------------------------------------------------------- */
/* This function stops a running script.
/* ----------------------------------------------------------------------- */
-int gpioDeleteScript(int script_id);
+int gpioDeleteScript(unsigned script_id);
/* ----------------------------------------------------------------------- */
/* This function deletes a stored script.
Returns the actual length of the delay in microseconds.
*/
-
+#define PI_MAX_MICS_DELAY 1000000 /* 1 second */
+#define PI_MAX_MILS_DELAY 60000 /* 60 seconds */
/*-------------------------------------------------------------------------*/
uint32_t gpioTick(void);
int value);
/*-------------------------------------------------------------------------*/
/* Used to tune internal settings.
+
Not intended for general use.
*/
/*-------------------------------------------------------------------------*/
-int gpioWaveAddSPI(
- gpioSPI_t *spi,
+int rawWaveAddSPI(
+ rawSPI_t *spi,
unsigned offset,
unsigned ss,
uint8_t *tx_bits,
Returns the new total number of pulses in the current waveform if OK,
otherwise PI_BAD_USER_GPIO, PI_BAD_SER_OFFSET, or PI_TOO_MANY_PULSES.
+
+ Not intended for general use.
*/
+/* ----------------------------------------------------------------------- */
+unsigned rawWaveCB(void);
+/* ----------------------------------------------------------------------- */
+/*
+ Returns the number of the cb being currently output.
+
+ Not intended for general use.
+*/
+
+/* ----------------------------------------------------------------------- */
+rawCbs_t * rawWaveCBAdr(int n);
+/* ----------------------------------------------------------------------- */
+/*
+ Return the Linux address of contol block n.
+
+ Not intended for general use.
+*/
/* ----------------------------------------------------------------------- */
-uint32_t waveGetRawOut(int pos);
+uint32_t rawWaveGetOut(int pos);
/* ----------------------------------------------------------------------- */
/* Gets the wave output parameter stored at pos.
+
Not intended for general use.
*/
/* ----------------------------------------------------------------------- */
-void waveSetRawOut(int pos, uint32_t value);
+void rawWaveSetOut(int pos, uint32_t value);
/* ----------------------------------------------------------------------- */
/* Sets the wave output parameter stored at pos to value.
+
Not intended for general use.
*/
/* ----------------------------------------------------------------------- */
-uint32_t waveGetRawIn(int pos);
+uint32_t rawWaveGetIn(int pos);
/* ----------------------------------------------------------------------- */
/* Gets the wave input value parameter stored at pos.
+
Not intended for general use.
*/
/* ----------------------------------------------------------------------- */
-void waveSetRawIn(int pos, uint32_t value);
+void rawWaveSetIn(int pos, uint32_t value);
/* ----------------------------------------------------------------------- */
/* Sets the wave input value stored at pos to value.
+
Not intended for general use.
*/
/*-------------------------------------------------------------------------*/
-void gpioDumpWave(void);
+void rawDumpWave(void);
/*-------------------------------------------------------------------------*/
/* Used to print a readable version of the current waveform to stderr.
+
Not intended for general use.
*/
/*-------------------------------------------------------------------------*/
-void gpioDumpScript(int s);
+void rawDumpScript(int s);
/*-------------------------------------------------------------------------*/
/* Used to print a readable version of a script to stderr.
+
Not intended for general use.
*/
#define PI_CMD_SLR 43
#define PI_CMD_SLRC 44
#define PI_CMD_PROCP 45
-#define PI_CMD_MICRO 46
-#define PI_CMD_MILLI 47
+#define PI_CMD_MICS 46
+#define PI_CMD_MILS 47
+#define PI_CMD_PARSE 48
+#define PI_CMD_WVCRE 49
+#define PI_CMD_WVDEL 50
+#define PI_CMD_WVTX 51
+#define PI_CMD_WVTXR 52
+#define PI_CMD_WVNEW 53
/*
#define PI_CMD_SCRIPT 800
-#define PI_CMD_ADDI 800
-#define PI_CMD_ADDV 801
-#define PI_CMD_ANDI 802
-#define PI_CMD_ANDV 803
-#define PI_CMD_CALL 804
-#define PI_CMD_CMPI 805
-#define PI_CMD_CMPV 806
-#define PI_CMD_DCRA 807
-#define PI_CMD_DCRV 808
-#define PI_CMD_HALT 809
-#define PI_CMD_INRA 810
-#define PI_CMD_INRV 811
-#define PI_CMD_JM 812
-#define PI_CMD_JMP 813
-#define PI_CMD_JNZ 814
-#define PI_CMD_JP 815
-#define PI_CMD_JZ 816
-#define PI_CMD_LABEL 817
-#define PI_CMD_LDAI 818
-#define PI_CMD_LDAP 819
-#define PI_CMD_LDAV 820
-#define PI_CMD_LDPA 821
-#define PI_CMD_LDVA 822
-#define PI_CMD_LDVI 823
-#define PI_CMD_LDVV 824
-#define PI_CMD_ORI 827
-#define PI_CMD_ORV 828
-#define PI_CMD_POPA 829
-#define PI_CMD_POPV 830
-#define PI_CMD_PUSHA 831
-#define PI_CMD_PUSHV 832
-#define PI_CMD_RET 833
-#define PI_CMD_RAL 834
-#define PI_CMD_RAR 835
-#define PI_CMD_SUBI 836
-#define PI_CMD_SUBV 837
-#define PI_CMD_SWAPA 838
-#define PI_CMD_SWAPV 839
-#define PI_CMD_SYS 840
-#define PI_CMD_WAITI 841
-#define PI_CMD_WAITV 842
-#define PI_CMD_XORI 843
-#define PI_CMD_XORV 844
+#define PI_CMD_ADD 800
+#define PI_CMD_AND 801
+#define PI_CMD_CALL 802
+#define PI_CMD_CMP 803
+#define PI_CMD_DCR 804
+#define PI_CMD_DCRA 805
+#define PI_CMD_DIV 806
+#define PI_CMD_HALT 807
+#define PI_CMD_INR 808
+#define PI_CMD_INRA 809
+#define PI_CMD_JM 810
+#define PI_CMD_JMP 811
+#define PI_CMD_JNZ 812
+#define PI_CMD_JP 813
+#define PI_CMD_JZ 814
+#define PI_CMD_TAG 815
+#define PI_CMD_LD 816
+#define PI_CMD_LDA 817
+#define PI_CMD_MLT 818
+#define PI_CMD_MOD 819
+#define PI_CMD_OR 820
+#define PI_CMD_POP 821
+#define PI_CMD_POPA 822
+#define PI_CMD_PUSH 823
+#define PI_CMD_PUSHA 824
+#define PI_CMD_RET 825
+#define PI_CMD_RL 826
+#define PI_CMD_RLA 827
+#define PI_CMD_RR 828
+#define PI_CMD_RRA 829
+#define PI_CMD_STA 830
+#define PI_CMD_SUB 831
+#define PI_CMD_SYS 832
+#define PI_CMD_WAIT 833
+#define PI_CMD_X 834
+#define PI_CMD_XA 835
+#define PI_CMD_XOR 836
/*-------------------------------------------------------------------------*/
#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_PULSELEN -46 /* trigger pulse length > 50 */
#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 */
#define PI_BAD_PARAM_NUM -52 /* script parameter must be 0-9 */
-#define PI_DUP_LABEL -53 /* script has duplicate label */
-#define PI_TOO_MANY_LABELS -54 /* script has too many labels */
+#define PI_DUP_TAG -53 /* script has duplicate tag */
+#define PI_TOO_MANY_TAGS -54 /* script has too many tags */
#define PI_BAD_SCRIPT_CMD -55 /* illegal script command */
#define PI_BAD_VAR_NUM -56 /* script variable must be 0-149 */
#define PI_NO_SCRIPT_ROOM -57 /* no more room for scripts */
#define PI_SOCK_WRIT_FAILED -60 /* socket write failed */
#define PI_TOO_MANY_PARAM -61 /* too many script parameters > 10 */
#define PI_NOT_HALTED -62 /* script already running or failed */
+#define PI_BAD_TAG -63 /* script has unresolved tag */
+#define PI_BAD_MICS_DELAY -64 /* bad MICS delay (too large) */
+#define PI_BAD_MILS_DELAY -65 /* bad MILS delay (too large) */
+#define PI_BAD_WAVE_ID -66 /* non existent wave id */
+#define PI_TOO_MANY_CBS -67 /* No more CBs for waveform */
+#define PI_TOO_MANY_OOL -68 /* No more OOL for waveform */
+#define PI_EMPTY_WAVEFORM -69 /* attempt to create an empty waveform */
+#define PI_NO_WAVEFORM_ID -70 /* no more waveforms */
/*-------------------------------------------------------------------------*/
- provision of servo pulses on any number of gpios 0-31 simultaneously.
-- callbacks when any of gpios 0-31 change state.
+- callbacks when any of gpios 0-31 change state (callbacks receive the
+ time of the event accurate to a few microseconds).
- reading/writing gpios and setting their modes (typically input
or output).
- reading/writing all of the gpios in a bank (0-31, 32-53) as a single
operation.
+- creating and transmitting precisely timed waveforms (accurate
+ to a few microseconds).
+
+- creating and running scripts on the pigpio daemon.
+
Notes
ALL gpios are identified by their Broadcom number.
import os
import atexit
-VERSION = "1.4"
+VERSION = "1.5"
# gpio levels
_PI_CMD_SLR= 43
_PI_CMD_SLRC= 44
_PI_CMD_PROCP=45
-
+_PI_CMD_MICRO=46
+_PI_CMD_MILLI=47
+_PI_CMD_PARSE=48
+_PI_CMD_WVCRE=49
+_PI_CMD_WVDEL=50
+_PI_CMD_WVTX =51
+_PI_CMD_WVTXR=52
_PI_CMD_NOIB= 99
-
# pigpio error numbers
_PI_INIT_FAILED =-1
PI_GPIO_IN_USE =-50
PI_BAD_SERIAL_COUNT =-51
PI_BAD_PARAM_NUM =-52
-PI_DUP_LABEL =-53
-PI_TOO_MANY_LABELS =-54
+PI_DUP_TAG =-53
+PI_TOO_MANY_TAGS =-54
PI_BAD_SCRIPT_CMD =-55
PI_BAD_VAR_NUM =-56
PI_NO_SCRIPT_ROOM =-57
PI_SOCK_WRIT_FAILED =-60
PI_TOO_MANY_PARAM =-61
PI_NOT_HALTED =-62
+PI_BAD_TAG =-63
+PI_BAD_MICS_DELAY =-64
+PI_BAD_MILS_DELAY =-65
+PI_BAD_WAVE_ID =-66
+PI_TOO_MANY_CBS =-67
+PI_TOO_MANY_OOL =-68
+PI_EMPTY_WAVEFORM =-69
+PI_NO_WAVEFORM_ID =-70
# pigpio error text
[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_PULSELEN , "trigger pulse length > 50"],
[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"],
[PI_BAD_PARAM_NUM , "script parameter must be 0-9"],
- [PI_DUP_LABEL , "script has duplicate label"],
- [PI_TOO_MANY_LABELS , "script has too many labels"],
+ [PI_DUP_TAG , "script has duplicate tag"],
+ [PI_TOO_MANY_TAGS , "script has too many tags"],
[PI_BAD_SCRIPT_CMD , "illegal script command"],
[PI_BAD_VAR_NUM , "script variable must be 0-149"],
[PI_NO_SCRIPT_ROOM , "no more room for scripts"],
[PI_SOCK_WRIT_FAILED , "socket write failed"],
[PI_TOO_MANY_PARAM , "too many script parameters (> 10)"],
[PI_NOT_HALTED , "script already running or failed"],
+ [PI_BAD_TAG , "script has unresolved tag"],
+ [PI_BAD_MICS_DELAY , "bad MICS delay (too large)"],
+ [PI_BAD_MILS_DELAY , "bad MILS delay (too large)"],
+ [PI_BAD_WAVE_ID , "non existent wave id"],
+ [PI_TOO_MANY_CBS , "No more CBs for waveform"],
+ [PI_TOO_MANY_OOL , "No more OOL for waveform"],
+ [PI_EMPTY_WAVEFORM , "attempt to create an empty waveform"],
+ [PI_NO_WAVEFORM_ID , "No more waveform ids"],
]
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)
-
+ msg = struct.pack('IIII', cmd, p1, p2, 0)
+ for ext in extents: msg += ext
+ sock.sendall(msg)
x, y, z, res = struct.unpack('IIII', sock.recv(16))
return res
else:
_notify.append(self.callb)
self.start = time.time()
while (self.trigger == False) and ((time.time()-self.start) < timeout):
- time.sleep(0.1)
+ time.sleep(0.05)
_notify.remove(self.callb)
def func(self, gpio, level, tick):
Example 1: standard 50 Hz hobby servo updates
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
import time
Example 2: 400 Hz ESC type servo updates
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
import time
Example
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
import time
Example
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
Example
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
Example
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
import time
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.
+ Clears all waveforms and any data added by calls to the
+ wave_add_* functions.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVCLR, 0, 0))
+def wave_add_new():
+ """
+ Starts a new empty waveform. You wouldn't normally need
+ to call this function as it is automatically called after a
+ waveform is created with the wave_create function.
+ """
+ return _u2i(_pigpio_command(_control, _PI_CMD_WVNEW, 0, 0))
+
def wave_add_generic(pulses):
"""
Adds a list of pulses to the current waveform.
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
+ G1=4
+ G2=22
pigpio.start()
- s1 = stepper(14, 15, 18, 17)
- s2 = stepper(24, 25, 8, 7)
+ pigpio.set_mode(G1, pigpio.OUTPUT)
+ pigpio.set_mode(G2, pigpio.OUTPUT)
+
+
+ flash_500=[] # flash every 500 ms
+ flash_100=[] # flash every 100 ms
- f1=[] # pulses to drive stepper 1 forward
- b2=[] # pulses to drive stepper 2 backward
+ # ON OFF DELAY
- 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))
+ flash_500.append(pigpio.pulse(1<<G1, 1<<G2, 500000))
+ flash_500.append(pigpio.pulse(1<<G2, 1<<G1, 500000))
- pigpio.wave_clear() # initialise a new waveform
+ flash_100.append(pigpio.pulse(1<<G1, 1<<G2, 100000))
+ flash_100.append(pigpio.pulse(1<<G2, 1<<G1, 100000))
- pigpio.wave_add_generic(f1) # add stepper 1 forward
- pigpio.wave_add_generic(b2) # add stepper 2 backward
+ pigpio.wave_clear() # clear any existing waveforms
- pigpio.wave_tx_repeat() # repeately transmit pulses
+ pigpio.wave_add_generic(flash_500) # 500 ms flashes
+ f500 = pigpio.wave_create() # create and save id
- time.sleep(10)
+ pigpio.wave_add_generic(flash_100) # 100 ms flashes
+ f100 = pigpio.wave_create() # create and save id
+
+ pigpio.wave_send_repeat(f500)
+
+ time.sleep(4)
+
+ pigpio.wave_send_repeat(f100)
+
+ time.sleep(4)
+
+ pigpio.wave_send_repeat(f500)
+
+ time.sleep(4)
pigpio.wave_tx_stop() # stop waveform
+ pigpio.wave_clear() # clear all waveforms
+
pigpio.stop()
"""
# pigpio message format
# 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))
+ if len(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))
+ else:
+ return 0
def wave_add_serial(user_gpio, baud, offset, data):
"""
import pigpio
- GPIO=24
+ TX_GPIO=22
pigpio.start()
pigpio.set_mode(TX_GPIO, pigpio.OUTPUT)
- pigpio.wave_clear() # initialise waveform
+ pigpio.wave_clear() # clear all waveforms
for i in range(10):
pigpio.wave_add_serial(
- GPIO, 9600, i*2000000, "{} seconds in.\r\n".format(i*2))
+ TX_GPIO, 300, i*2000000, "{} seconds in.\r\n".format(i*2))
+
+ id = pigpio.wave_create()
- pigpio.wave_tx_start()
+ pigpio.wave_send_once(id)
time.sleep(22)
+ pigpio.write(TX_GPIO, 0)
+
pigpio.stop()
"""
# pigpio message format
# 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))
+ if len(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))
+ else:
+ return 0
-def wave_tx_busy():
+def wave_create():
"""
- Checks to see if a waveform is currently being transmitted.
+ Creates a waveform from the data provided by the prior calls to the
+ wave_add_* functions. Upon success a positive wave id is returned.
- Returns 1 if a waveform is currently being transmitted, otherwise 0.
+ The data provided by the wave_add_* functions is consumed by this
+ function.
+
+ As many waveforms may be created as there is space available. The
+ wave id is passed to wave_send_* to specify the waveform to transmit.
+
+ Normal usage would be
+
+ Step 1. wave_clear to clear all waveforms and added data.
+
+ Step 2. wave_add_* calls to supply the waveform data.
+
+ Step 3. wave_create to create the waveform and get a unique id
+
+ Repeat steps 2 and 3 as needed.
+
+ Step 4. wave_send_* with the id of the waveform to transmit.
+
+ A waveform comprises one or 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_WVBSY, 0, 0))
+ return _u2i(_pigpio_command(_control, _PI_CMD_WVCRE, 0, 0))
-def wave_tx_stop():
+def wave_delete(wave_id):
"""
- Stops the transmission of the current waveform.
+ Deletes all created waveforms with ids greater than or equal
+ to wave_id.
- Returns 0 if OK.
+ Wave ids are allocated in order, 0, 1, 2, etc.
- This function is intended to stop a waveform started with
- wave_tx_repeat().
+ Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
"""
- return _u2i(_pigpio_command(_control, _PI_CMD_WVHLT, 0, 0))
+ return _u2i(_pigpio_command(_control, _PI_CMD_WVDEL, wave_id, 0))
def wave_tx_start():
"""
- Transmits the current waveform. The waveform is sent once.
+ This function is deprecated and will be removed.
- Returns the number of cbs in the waveform if OK,
- otherwise PI_BAD_WAVE_MODE.
+ Use wave_create/wave_send_* instead.
"""
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.
+ This function is deprecated and will be removed.
- Returns the number of cbs in the waveform if OK,
- otherwise PI_BAD_WAVE_MODE.
+ Use wave_create/wave_send_* instead.
"""
return _u2i(_pigpio_command(_control, _PI_CMD_WVGOR, 0, 0))
+def wave_send_once(wave_id):
+ """
+ Transmits the waveform with id wave_id. The waveform is sent once.
+
+ Returns the number of cbs in the waveform if OK,
+ otherwise PI_BAD_WAVE_ID, or PI_BAD_WAVE_MODE.
+ """
+ return _u2i(_pigpio_command(_control, _PI_CMD_WVTX, wave_id, 0))
+
+def wave_send_repeat(wave_id):
+ """
+ Transmits the waveform with id wave_id. The waveform repeats until
+ wave_tx_stop is called or another call to wave_send_* is made.
+
+ Returns the number of cbs in the waveform if OK,
+ otherwise PI_BAD_WAVE_ID, or PI_BAD_WAVE_MODE.
+ """
+ return _u2i(_pigpio_command(_control, _PI_CMD_WVTXR, wave_id, 0))
+
+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_send_repeatedly.
+ """
+ return _u2i(_pigpio_command(_control, _PI_CMD_WVHLT, 0, 0))
+
def wave_get_micros():
"""
Returns the length in microseconds of the current waveform.
pigpio.start()
- for i in range(10):
+ for i in range(5):
pigpio.gpio_trigger(GPIO, (i*5)+10, 1)
time.sleep(1)
Example 1: user supplied edge and callback
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
import time
Example 2: user supplied edge, default (tally) callback
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
import time
Example 3: default edge and (tally) callback
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
import time
Example 1: default edge and timeout
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
import time
Example 2: user supplied edge and timeout
- #!/usr/bin/python
+ #!/usr/bin/env python
import pigpio
import time
*/
/*
-This version is for pigpio version 11+
+This version is for pigpio version 14+
*/
#include <sys/types.h>
static unsigned socketPort = PI_DEFAULT_SOCKET_PORT;
static uint64_t updateMask = -1;
+static int updateMaskSet = 0;
+
static FILE * errFifo;
void fatal(char *fmt, ...)
case 'x':
mask = strtoll(optarg, &endptr, 0);
printf("mask=%llx\n", mask);
- if (!*endptr) updateMask = mask;
+ if (!*endptr)
+ {
+ updateMask = mask;
+ updateMaskSet = 1;
+ }
else fatal("invalid -x option (%s)", optarg);
break;
gpioCfgSocketPort(socketPort);
- if (updateMask != -1) gpioCfgPermissions(updateMask);
+ if (updateMaskSet) gpioCfgPermissions(updateMask);
/* start library */
int wave_clear(void)
{return pigpio_command(gPigCommand, PI_CMD_WVCLR, 0, 0);}
+int wave_add_new(void)
+ {return pigpio_command(gPigCommand, PI_CMD_WVNEW, 0, 0);}
+
int wave_add_generic(unsigned numPulses, gpioPulse_t *pulses)
{
gpioExtent_t ext[1];
gpioPulse_t[] pulses
*/
+ if (!numPulses) return 0;
+
ext[0].size = numPulses * sizeof(gpioPulse_t);
ext[0].ptr = pulses;
char[] str
*/
+ if (!numChar) return 0;
+
ext[0].size = sizeof(unsigned);
ext[0].ptr = &baud;
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_create(void)
+ {return pigpio_command(gPigCommand, PI_CMD_WVCRE, 0, 0);}
-int wave_tx_stop(void)
- {return pigpio_command(gPigCommand, PI_CMD_WVHLT, 0, 0);}
+int wave_delete(unsigned wave_id)
+ {return pigpio_command(gPigCommand, PI_CMD_WVDEL, wave_id, 0);}
-int wave_tx_start(void)
+int wave_tx_start(void) /* DEPRECATED */
{return pigpio_command(gPigCommand, PI_CMD_WVGO, 0, 0);}
-int wave_tx_repeat(void)
+int wave_tx_repeat(void) /* DEPRECATED */
{return pigpio_command(gPigCommand, PI_CMD_WVGOR, 0, 0);}
+int wave_send_once(unsigned wave_id)
+ {return pigpio_command(gPigCommand, PI_CMD_WVTX, 0, 0);}
+
+int wave_send_repeat(unsigned wave_id)
+ {return pigpio_command(gPigCommand, PI_CMD_WVTXR, 0, 0);}
+
+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_get_micros(void)
{return pigpio_command(gPigCommand, PI_CMD_WVSM, 0, 0);}
(gPigCommand, PI_CMD_PROCR, script_id, numPar, 1, ext);
}
-int script_status(int script_id, uint32_t *param)
+int script_status(unsigned script_id, uint32_t *param)
{
int status;
- uint32_t p[MAX_SCRIPT_PARAMS];
+ uint32_t p[PI_MAX_SCRIPT_PARAMS];
status = pigpio_command(gPigCommand, PI_CMD_PROCP, script_id, 0);
#include "pigpio.h"
-#define PIGPIOD_IF_VERSION 4
+#define PIGPIOD_IF_VERSION 5
typedef enum
{
int wave_clear(void);
-/* This function initialises a new waveform.
+/* This function clears all waveforms and any data added by calls to the
+ wave_add_* functions.
Returns 0 if OK.
+*/
+
+int wave_add_new(void);
+/* This function starts a new empty waveform. You wouldn't normally need
+ to call this function as it is automatically called after a waveform is
+ created with the wave_create function.
+
+ Returns 0 if OK.
+*/
+
+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).
- A waveform comprises one of more pulses. Each pulse consists of a
+ 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_create(void);
+/* This function creates a waveform from the data provided by the prior
+ calls to the wave_add_* functions. Upon success a positive wave id
+ is returned.
+
+ The data provided by the wave_add_* functions is consumed by this
+ function.
+
+ As many waveforms may be created as there is space available. The
+ wave id is passed to wave_send_* to specify the waveform to transmit.
+
+ Normal usage would be
+
+ Step 1. wave_clear to clear all waveforms and added data.
+
+ Step 2. wave_add_* calls to supply the waveform data.
+
+ Step 3. wave_create to create the waveform and get a unique id
+
+ Repeat steps 2 and 3 as needed.
+
+ Step 4. wave_send_* with the id of the waveform to transmit.
+
+ A waveform comprises one or more pulses. Each pulse consists of a
gpioPulse_t structure.
typedef struct
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.
+ Returns the new waveform id if OK, otherwise PI_EMPTY_WAVEFORM,
+ PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
*/
-int wave_tx_stop(void);
-/* This function stops the transmission of the current waveform.
- Returns 0 if OK.
+int wave_delete(unsigned wave_id);
+/* This function deletes all created waveforms with ids greater than or
+ equal to wave_id.
- This function is intended to stop a waveform started with the repeat mode.
+ Wave ids are allocated in order, 0, 1, 2, etc.
+
+ Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
*/
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.
+/* This function is deprecated and should no longer be used. Use
+ wave_create/wave_send_* instead.
*/
int wave_tx_repeat(void);
-/* This function transmits the current waveform. The waveform repeats
- endlessly until wave_tx_stop is called.
+/* This function is deprecated and should no longer be used. Use
+ wave_create/wave_send_* instead.
+*/
+
+int wave_send_once(unsigned wave_id);
+/* This function transmits the waveform with id wave_id. The waveform
+ is sent once.
Returns the number of DMA control blocks in the waveform if OK,
- otherwise PI_BAD_WAVE_MODE.
+ otherwise PI_BAD_WAVE_ID, or PI_BAD_WAVE_MODE.
*/
-int wave_add_generic(unsigned numPulses, gpioPulse_t *pulses);
-/* This function adds a number of pulses to the current waveform.
+int wave_send_repeat(unsigned wave_id);
+/* This function transmits the waveform with id wave_id. The waveform
+ cycles until cancelled (either by the sending of a new waveform or
+ by wave_tx_stop).
- Returns the new total number of pulses in the current waveform if OK,
- otherwise PI_TOO_MANY_PULSES.
+ Returns the number of DMA control blocks in the waveform if OK,
+ otherwise PI_BAD_WAVE_ID, or PI_BAD_WAVE_MODE.
+*/
- 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.
+int wave_tx_busy(void);
+/* This function checks to see if a waveform is currently being
+ transmitted.
- If the added waveform is intended to start after or within the existing
- waveform then the first pulse should consist solely of a delay.
+ Returns 1 if a waveform is currently being transmitted, otherwise 0.
*/
-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:
+int wave_tx_stop(void);
+/* This function stops the transmission of the current waveform.
- The serial data is formatted as one start bit, eight data bits, and one
- stop bit.
+ Returns 0 if OK.
- It is legal to add serial data streams with different baud rates to
- the same waveform.
+ This function is intended to stop a waveform started with the repeat mode.
*/
int wave_get_micros(void);
the script as param 0 to param 9..
*/
-int script_status(int script_id, uint32_t *param);
+int script_status(unsigned script_id, uint32_t *param);
/* This function returns the run status of a stored script as well
as the current values of parameters 0 to 9.
*/
/*
-This version is for pigpio version 13+
+This version is for pigpio version 14+
*/
#include <stdio.h>
char command_buf[8192];
char response_buf[8192];
+#define SOCKET_OPEN_FAILED -1
+
void fatal(char *fmt, ...)
{
char buf[128];
err = getaddrinfo(addrStr, portStr, &hints, &res);
- if (err) return -1;
+ if (err) return SOCKET_OPEN_FAILED;
for (rp=res; rp!=NULL; rp=rp->ai_next)
{
freeaddrinfo(res);
- if (rp == NULL) return -1;
+ if (rp == NULL) return SOCKET_OPEN_FAILED;
return sock;
}
p = (uint32_t *)response_buf;
- for (i=0; i<MAX_SCRIPT_PARAMS; i++)
+ for (i=0; i<PI_MAX_SCRIPT_PARAMS; i++)
{
printf(" %d", p[i]);
}
{
recv(sock,
response_buf,
- sizeof(uint32_t)*MAX_SCRIPT_PARAMS,
+ sizeof(uint32_t)*PI_MAX_SCRIPT_PARAMS,
MSG_WAITALL);
}
break;
cmdCmd_t cmd;
uint32_t p[10];
void *v[10];
- gpioCtlParse_t ctl;
+ cmdCtlParse_t ctl;
+ cmdScript_t s;
- sock = openSocket();
+ sock = openSocket();
- if (sock != -1)
- {
- command_buf[0] = 0;
- l = 0;
- pp = 0;
+ command_buf[0] = 0;
+ l = 0;
+ pp = 0;
- for (i=1; i<argc; i++)
- {
- l += (strlen(argv[i]) + 1);
- if (l < sizeof(command_buf))
- {sprintf(command_buf+pp, "%s ", argv[i]); pp=l;}
- }
+ for (i=1; i<argc; i++)
+ {
+ l += (strlen(argv[i]) + 1);
+ if (l < sizeof(command_buf))
+ {sprintf(command_buf+pp, "%s ", argv[i]); pp=l;}
+ }
- if (pp) {command_buf[--pp] = 0;}
+ if (pp) {command_buf[--pp] = 0;}
- ctl.flags = 0;
- ctl.eaten = 0;
+ ctl.eaten = 0;
- len = strlen(command_buf);
- idx = 0;
+ len = strlen(command_buf);
+ idx = 0;
- while ((idx >= 0) && (ctl.eaten < len))
+ while ((idx >= 0) && (ctl.eaten < len))
+ {
+ if ((idx=cmdParse(command_buf, p, v, &ctl)) >= 0)
{
- if ((idx=cmdParse(command_buf, p, v, &ctl)) >= 0)
- {
- command = p[0];
+ command = p[0];
- if (command < PI_CMD_SCRIPT)
+ if (command < PI_CMD_SCRIPT)
+ {
+ if (command == PI_CMD_HELP)
+ {
+ printf(cmdUsage);
+ }
+ else if (command == PI_CMD_PARSE)
+ {
+ cmdParseScript(v[1], &s, 1);
+ if (s.par) free (s.par);
+ }
+ else
{
cmd.cmd = command;
cmd.p1 = p[1];
{
case PI_CMD_WVAS:
cmd.p2 = p[4];
- break;
+ break;
case PI_CMD_PROC:
cmd.p2 = 0;
break;
}
- if (send(sock, &cmd, sizeof(cmdCmd_t), 0) == sizeof(cmdCmd_t))
+ if (sock != SOCKET_OPEN_FAILED)
{
- put_extensions(sock, command, p, v);
-
- if (recv(sock, &cmd, sizeof(cmdCmd_t), MSG_WAITALL) ==
+ if (send(sock, &cmd, sizeof(cmdCmd_t), 0) ==
sizeof(cmdCmd_t))
{
- get_extensions(sock, command, cmd.res);
+ put_extensions(sock, command, p, v);
- print_result(sock, cmdInfo[idx].rv, cmd);
+ if (recv(sock, &cmd, sizeof(cmdCmd_t), MSG_WAITALL) ==
+ sizeof(cmdCmd_t))
+ {
+ get_extensions(sock, command, cmd.res);
+
+ print_result(sock, cmdInfo[idx].rv, cmd);
+ }
+ else fatal("recv failed, %m");
}
- else fatal("recv failed, %m");
+ else fatal("send failed, %m");
}
- else fatal("send failed, %m");
+ else fatal("connect failed");
}
- else fatal("%s only allowed within a script", cmdInfo[idx].name);
}
- else fatal("%s? pigs h for help", cmdStr());
+ else fatal("%s only allowed within a script", cmdInfo[idx].name);
+ }
+ else
+ {
+ if (idx == CMD_UNKNOWN_CMD)
+ fatal("%s? unknown command, pigs h for help", cmdStr());
+ else
+ fatal("%s: bad parameter, pigs h for help", cmdStr());
}
}
- else fatal("connect failed, %m");
- close(sock);
+ if (sock >= 0) close(sock);
return 0;
}
from distutils.core import setup
setup(name='pigpio',
- version='1.4',
+ version='1.5',
author='joan',
author_email='joan@abyz.co.uk',
maintainer='joan',
--- /dev/null
+#!/bin/bash
+#
+rm -rf PIGPIO
+mkdir PIGPIO
+#
+cp command.c PIGPIO
+cp command.h PIGPIO
+cp Makefile PIGPIO
+cp MakeRemote PIGPIO
+cp pig2vcd.c PIGPIO
+cp pigpio.c PIGPIO
+cp pigpio.h PIGPIO
+cp pigpiod.c PIGPIO
+cp pigpiod_if.c PIGPIO
+cp pigpiod_if.h PIGPIO
+cp pigpio.py PIGPIO
+cp pigs.c PIGPIO
+cp README PIGPIO
+cp setup.py PIGPIO
+cp UNLICENCE PIGPIO
+cp x_pigpio.c PIGPIO
+cp x_pigpio.py PIGPIO
+cp x_pigpiod_if.c PIGPIO
+cp x_pigs PIGPIO
+cp x_pipe PIGPIO
+#
+zip -r pigpio-$1.zip PIGPIO
+tar cvf pigpio-$1.tar PIGPIO
+
/*
gcc -o x_pigpio x_pigpio.c -lpigpio -lrt -lpthread
sudo ./x_pigpio
+
+*** WARNING ************************************************
+* *
+* All the tests make extensive use of gpio 4 (pin P1-7). *
+* Ensure that either nothing or just a LED is connected to *
+* gpio 4 before running any of the tests. *
+************************************************************
*/
#include <stdio.h>
gpioSetAlertFunc(GPIO, t6cbf);
- for (t=0; t<10; t++)
+ for (t=0; t<5; t++)
{
time_sleep(0.1);
p = 10 + (t*10);
tp += p;
- gpioTrigger(4, p, 1);
+ gpioTrigger(GPIO, p, 1);
}
time_sleep(0.2);
- CHECK(6, 1, t6_count, 10, 0, "gpio trigger count");
+ CHECK(6, 1, t6_count, 5, 0, "gpio trigger count");
CHECK(6, 2, t6_on, tp, 25, "gpio trigger pulse length");
}
p1 GPIO
*/
char *script="\
- ldap 0\
- ldva 0\
- label 0\
+ lda p0\
+ sta v0\
+ tag 0\
w p1 1\
- milli 5\
+ mils 5\
w p1 0\
- milli 5\
- dcrv 0\
- ldav 0\
- ldpa 9\
+ mils 5\
+ dcr v0\
+ lda v0\
+ sta p9\
jp 0";
printf("Script store/run/status/stop/delete tests.\n");
#!/usr/bin/env python
+#*** WARNING ************************************************
+#* *
+#* All the tests make extensive use of gpio 4 (pin P1-7). *
+#* Ensure that either nothing or just a LED is connected to *
+#* gpio 4 before running any of the tests. *
+#************************************************************
+
import time
import struct
c = pigpio.wave_get_max_cbs()
CHECK(5, 21, c, 25016, 0, "wave get max cbs")
+ e = pigpio.wave_clear()
+ CHECK(5, 22, e, 0, 0, "wave clear")
+
+ e = pigpio.wave_add_generic(wf)
+ CHECK(5, 23, e, 4, 0, "pulse, wave add generic")
+
+ w1 = pigpio.wave_create()
+ CHECK(5, 24, w1, 0, 0, "wave create")
+
+ e = pigpio.wave_send_repeat(w1)
+ CHECK(5, 25, e, 9, 0, "wave send repeat")
+
+ oc = t5_count
+ time.sleep(5)
+ c = t5_count - oc
+ CHECK(5, 26, c, 50, 1, "callback")
+
+ e = pigpio.wave_tx_stop()
+ CHECK(5, 27, e, 0, 0, "wave tx stop")
+
+ e = pigpio.wave_add_serial(GPIO, BAUD, 5000000, TEXT)
+ CHECK(5, 28, e, 3405, 0, "wave add serial")
+
+ w2 = pigpio.wave_create()
+ CHECK(5, 29, w2, 1, 0, "wave create")
+
+ e = pigpio.wave_send_once(w2)
+ CHECK(5, 30, e, 6811, 0, "wave send once")
+
+ oc = t5_count
+ time.sleep(3)
+ c = t5_count - oc
+ CHECK(5, 31, c, 0, 0, "callback")
+
+ oc = t5_count
+ while pigpio.wave_tx_busy():
+ time.sleep(0.1)
+ time.sleep(0.1)
+ c = t5_count - oc
+ CHECK(5, 32, c, 1702, 0, "wave tx busy, callback")
+
+ e = pigpio.wave_delete(0)
+ CHECK(5, 33, e, 0, 0, "wave delete")
+
t6_count=0
t6_on=0
t6_on_tick=None
t6cb = pigpio.callback(GPIO, pigpio.EITHER_EDGE, t6cbf)
- for t in range(10):
+ for t in range(5):
time.sleep(0.1)
p = 10 + (t*10)
tp += p;
- pigpio.gpio_trigger(4, p, 1)
+ pigpio.gpio_trigger(GPIO, p, 1)
time.sleep(0.5)
- CHECK(6, 1, t6_count, 10, 0, "gpio trigger count")
+ CHECK(6, 1, t6_count, 5, 0, "gpio trigger count")
CHECK(6, 2, t6_on, tp, 25, "gpio trigger pulse length")
# p0 number of loops
# p1 GPIO
script="""
- ldap 0
- ldva 0
- label 0
+ lda p0
+ sta v0
+ tag 0
w p1 1
- milli 5
+ mils 5
w p1 0
- milli 5
- dcrv 0
- ldav 0
- ldpa 9
+ mils 5
+ dcr v0
+ lda v0
+ sta p9
jp 0"""
t9cb = pigpio.callback(GPIO)
/*
gcc -o x_pigpiod_if x_pigpiod_if.c -lpigpiod_if -lrt -lpthread
sudo ./x_pigpiod_if
+
+*** WARNING ************************************************
+* *
+* All the tests make extensive use of gpio 4 (pin P1-7). *
+* Ensure that either nothing or just a LED is connected to *
+* gpio 4 before running any of the tests. *
+************************************************************
*/
#include <stdio.h>
time_sleep(0.2);
- for (t=0; t<10; t++)
+ for (t=0; t<5; t++)
{
time_sleep(0.1);
p = 10 + (t*10);
tp += p;
- gpio_trigger(4, p, 1);
+ gpio_trigger(GPIO, p, 1);
}
time_sleep(0.5);
- CHECK(6, 1, t6_count, 10, 0, "gpio trigger count");
+ CHECK(6, 1, t6_count, 5, 0, "gpio trigger count");
CHECK(6, 2, t6_on, tp, 25, "gpio trigger pulse length");
}
p1 GPIO
*/
char *script="\
- ldap 0\
- ldva 0\
- label 0\
+ lda p0\
+ sta v0\
+ tag 0\
w p1 1\
- milli 5\
+ mils 5\
w p1 0\
- milli 5\
- dcrv 0\
- ldav 0\
- ldpa 9\
+ mils 5\
+ dcr v0\
+ lda v0\
+ sta p9\
jp 0";
callback(GPIO, RISING_EDGE, t9cbf);
if [[ $s = "" ]]; then echo "BS2 ok"; else echo "BS2 fail ($s)"; fi
s=$(pigs h)
-if [[ ${#s} = 2999 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
+if [[ ${#s} = 3315 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
s=$(pigs hwver)
if [[ $s -ne 0 ]]; then echo "HWVER ok"; else echo "HWVER fail ($s)"; fi
-s=$(pigs micro 1000)
-if [[ $s = "" ]]; then echo "MICRO ok"; else echo "MICRO fail ($s)"; fi
+s=$(pigs mics 1000)
+if [[ $s = "" ]]; then echo "MICS ok"; else echo "MICS fail ($s)"; fi
-s=$(pigs milli 10)
-if [[ $s = "" ]]; then echo "MILLI ok"; else echo "MILLI fail ($s)"; fi
+s=$(pigs mils 10)
+if [[ $s = "" ]]; then echo "MILS ok"; else echo "MILS fail ($s)"; fi
s=$(pigs modes $GPIO 0)
s=$(pigs modeg $GPIO)
if [[ $s = 800 ]]; then echo "PFS-b ok"; else echo "PFS-b fail ($s)"; fi
s=$(pigs pigpv)
-if [[ $s = 13 ]]; then echo "PIGPV ok"; else echo "PIGPV fail ($s)"; fi
+if [[ $s = 14 ]]; then echo "PIGPV ok"; else echo "PIGPV fail ($s)"; fi
s=$(pigs prs $GPIO 255)
if [[ $s = 250 ]]; then echo "PRG-a ok"; else echo "PRG-a fail ($s)"; fi
s=$(pigs prg $GPIO)
if [[ $s = 255 ]]; then echo "PRG-b ok"; else echo "PRG-b fail ($s)"; fi
-p=$(pigs proc ldap 0 ldpa 1 ldai 1234 ldpa 0 label 999 milli 1000 jmp 999)
+p=$(pigs proc ld p1 p0 ld p0 1234 tag 999 mils 1000 jmp 999)
if [[ $p -ge 0 && $p -le 31 ]]
then echo "PROC($p) ok"
else echo "PROC($p) fail ($s)"
s=$(pigs slrc $GPIO)
if [[ $s = 0 ]]; then echo "SLR-g ok"; else echo "SLR-g fail ($s)"; fi
-t1=$(pigs t)
-t2=$(pigs tick)
-s=$(($t2-$t1))
-if [[ $s -gt 0 && $s -lt 20000 ]]
+t=$(pigs t tick)
+v=(${t// / })
+s=$((v[1]-v[0]))
+if [[ $s -gt 0 && $s -lt 2000 ]]
then echo "TICK ok"
else echo "TICK fail($s)"
fi
echo "h" >/dev/pigpio
read -t 1 s </dev/pigout
-if [[ $s = "BC1 v Clear gpios defined by mask v in bank 1." ]]
+if [[ $s = "BC1 v Clear gpios specified by mask v in bank 1." ]]
then echo "HELP-a ok"
else echo "HELP-a fail ($s)"
fi
read -t 1 -N 9000 </dev/pigout # dump rest of help
echo "help" >/dev/pigpio
read -t 1 s </dev/pigout
-if [[ $s = "BC1 v Clear gpios defined by mask v in bank 1." ]]
+if [[ $s = "BC1 v Clear gpios specified by mask v in bank 1." ]]
then echo "HELP-b ok"
else echo "HELP-b fail ($s)"
fi
read -t 1 s </dev/pigout
if [[ $s -ne 0 ]]; then echo "HWVER ok"; else echo "HWVER fail ($s)"; fi
-echo "micro 1000" >/dev/pigpio
+echo "mics 1000" >/dev/pigpio
read -t 1 s </dev/pigout
-if [[ $s = 0 ]]; then echo "MICRO ok"; else echo "MICRO fail ($s)"; fi
+if [[ $s = 0 ]]; then echo "MICS ok"; else echo "MICS fail ($s)"; fi
-echo "milli 10" >/dev/pigpio
+echo "mils 10" >/dev/pigpio
read -t 1 s </dev/pigout
-if [[ $s = 0 ]]; then echo "MILLI ok"; else echo "MILLI fail ($s)"; fi
+if [[ $s = 0 ]]; then echo "MILS ok"; else echo "MILS fail ($s)"; fi
echo "modes $GPIO 0" >/dev/pigpio
read -t 1 s </dev/pigout
echo "pigpv" >/dev/pigpio
read -t 1 s </dev/pigout
-if [[ $s = 13 ]]; then echo "PIGPV ok"; else echo "PIGPV fail ($s)"; fi
+if [[ $s = 14 ]]; then echo "PIGPV ok"; else echo "PIGPV fail ($s)"; fi
echo "prs $GPIO 255" >/dev/pigpio
read -t 1 s </dev/pigout
read -t 1 s </dev/pigout
if [[ $s = 255 ]]; then echo "PRG-b ok"; else echo "PRG-b fail ($s)"; fi
-echo "proc ldap 0 ldpa 1 ldai 29 ldpa 0 label 9 milli 1000 jmp 9" >/dev/pigpio
+echo "proc ld p1 p0 ld p0 29 tag 9 mils 1000 jmp 9" >/dev/pigpio
read -t 1 p </dev/pigout
if [[ $p -ge 0 && $p -le 31 ]]
then echo "PROC($p) ok"