diff --git a/command.c b/command.c
index 1bdb901..41c35ff 100644
--- a/command.c
+++ b/command.c
@@ -26,7 +26,7 @@ For more information, please refer to
*/
/*
-This version is for pigpio version 34+
+This version is for pigpio version 35+
*/
#include
@@ -458,11 +458,14 @@ static errInfo_t errInfo[]=
{PI_BAD_I2C_RLEN , "bad I2C read length"},
{PI_BAD_I2C_CMD , "bad I2C command"},
{PI_BAD_I2C_BAUD , "bad I2C baud rate, not 50-500k"},
- {PI_BAD_REPEAT_CNT , "bad repeat count, not 2-max"},
- {PI_BAD_REPEAT_WID , "bad repeat wave id"},
- {PI_TOO_MANY_COUNTS , "too many chain counters"},
- {PI_BAD_CHAIN_CMD , "malformed chain command string"},
- {PI_REUSED_WID , "wave already used in chain"},
+ {PI_CHAIN_LOOP_CNT , "bad chain loop count"},
+ {PI_BAD_CHAIN_LOOP , "empty chain loop"},
+ {PI_CHAIN_COUNTER , "too many chain counters"},
+ {PI_BAD_CHAIN_CMD , "bad chain command"},
+ {PI_BAD_CHAIN_DELAY , "bad chain delay micros"},
+ {PI_CHAIN_NESTING , "chain counters nested too deeply"},
+ {PI_CHAIN_TOO_BIG , "chain is too long"},
+ {PI_DEPRECATED , "deprecated function removed"},
};
@@ -535,6 +538,7 @@ int cmdParse(
char c;
uint32_t tp1, tp2, tp3;
int8_t to1, to2, to3;
+ int eaten;
/* Check that ext is big enough for the largest message. */
if (ext_len < (4 * CMD_MAX_PARAM)) return CMD_EXT_TOO_SMALL;
@@ -865,12 +869,16 @@ int cmdParse(
while (pars < CMD_MAX_PARAM)
{
- ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
- if ((to1 == CMD_NUMERIC) &&
- ((int)tp1>=0) && ((int)tp1<=255))
+ eaten = getNum(buf+ctl->eaten, &tp1, &to1);
+ if (to1 == CMD_NUMERIC)
{
- pars++;
- *p8++ = tp1;
+ if (((int)tp1>=0) && ((int)tp1<=255))
+ {
+ pars++;
+ *p8++ = tp1;
+ ctl->eaten += eaten;
+ }
+ else break; /* invalid number, end of command */
}
else break;
}
@@ -899,13 +907,16 @@ int cmdParse(
while (pars < 32)
{
- ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
- if ((to1 == CMD_NUMERIC) &&
- ((int)tp1>=0) &&
- ((int)tp1<=255))
+ eaten = getNum(buf+ctl->eaten, &tp1, &to1);
+ if (to1 == CMD_NUMERIC)
{
- pars++;
- *p8++ = tp1;
+ if (((int)tp1>=0) && ((int)tp1<=255))
+ {
+ pars++;
+ *p8++ = tp1;
+ ctl->eaten += eaten;
+ }
+ else break; /* invalid number, end of command */
}
else break;
}
@@ -940,15 +951,16 @@ int cmdParse(
while (pars < CMD_MAX_PARAM)
{
- ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
+ eaten = getNum(buf+ctl->eaten, &tp1, &to1);
if (to1 == CMD_NUMERIC)
{
if (((int)tp1>=0) && ((int)tp1<=255))
{
pars++;
*p8++ = tp1;
+ ctl->eaten += eaten;
}
- else valid = 0;
+ else break;
}
else break;
}
@@ -996,12 +1008,16 @@ int cmdParse(
p8 = ext + 12;
while (pars < CMD_MAX_PARAM)
{
- ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
- if ((to1 == CMD_NUMERIC) &&
- ((int)tp1>=0) && ((int)tp1<=255))
+ eaten = getNum(buf+ctl->eaten, &tp1, &to1);
+ if (to1 == CMD_NUMERIC)
{
- *p8++ = tp1;
- pars++;
+ if (((int)tp1>=0) && ((int)tp1<=255))
+ {
+ *p8++ = tp1;
+ pars++;
+ ctl->eaten += eaten;
+ }
+ else break; /* invalid number, end of command */
}
else break;
}
@@ -1022,12 +1038,16 @@ int cmdParse(
while (pars < CMD_MAX_PARAM)
{
- ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
- if ((to1 == CMD_NUMERIC) &&
- ((int)tp1>=0) && ((int)tp1<=255))
+ eaten = getNum(buf+ctl->eaten, &tp1, &to1);
+ if (to1 == CMD_NUMERIC)
{
- pars++;
- *p8++ = tp1;
+ if (((int)tp1>=0) && ((int)tp1<=255))
+ {
+ pars++;
+ *p8++ = tp1;
+ ctl->eaten += eaten;
+ }
+ else break; /* invalid number, end of command */
}
else break;
}
diff --git a/pigpio.3 b/pigpio.3
index 8d948bb..0006337 100644
--- a/pigpio.3
+++ b/pigpio.3
@@ -1683,8 +1683,9 @@ gpioWaveAddSerial(4, 9600, 8, 2, 1000000, MSG_LEN, data);
.IP "\fBint gpioWaveCreate(void)\fP"
.IP "" 4
This function creates a waveform from the data provided by the prior
-calls to the \fBgpioWaveAdd*\fP functions. Upon success a positive wave id
-is returned.
+calls to the \fBgpioWaveAdd*\fP functions. Upon success a wave id
+greater than or equal to 0 is returned, otherwise PI_EMPTY_WAVEFORM,
+PI_TOO_MANY_CBS, PI_TOO_MANY_OOL, or PI_NO_WAVEFORM_ID.
.br
@@ -1788,8 +1789,7 @@ PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
.IP "\fBint gpioWaveDelete(unsigned wave_id)\fP"
.IP "" 4
-This function deletes all created waveforms with ids greater than or
-equal to wave_id.
+This function deletes the waveform with id wave_id.
.br
@@ -1811,38 +1811,6 @@ Wave ids are allocated in order, 0, 1, 2, etc.
.br
Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
-.IP "\fBint gpioWaveTxStart(unsigned wave_mode)\fP"
-.IP "" 4
-This function creates and then transmits a waveform. The mode
-determines whether the waveform is sent once or cycles endlessly.
-
-.br
-
-.br
-NOTE: Any hardware PWM started by \fBgpioHardwarePWM\fP will be cancelled.
-
-.br
-
-.br
-
-.EX
-wave_mode: 0 (PI_WAVE_MODE_ONE_SHOT), 1 (PI_WAVE_MODE_REPEAT)
-.br
-
-.EE
-
-.br
-
-.br
-This function is deprecated and should no longer be used. Use
-\fBgpioWaveCreate\fP and \fBgpioWaveTxSend\fP instead.
-
-.br
-
-.br
-Returns the number of DMA control blocks in the waveform if OK,
-otherwise PI_BAD_WAVE_MODE.
-
.IP "\fBint gpioWaveTxSend(unsigned wave_id, unsigned wave_mode)\fP"
.IP "" 4
This function transmits the waveform with id wave_id. The mode
@@ -1884,7 +1852,7 @@ NOTE: Any hardware PWM started by \fBgpioHardwarePWM\fP will be cancelled.
.br
The waves to be transmitted are specified by the contents of buf
-which contains an ordered list of wave_ids and optional command
+which contains an ordered list of \fBwave_id\fPs and optional command
codes and related data.
.br
@@ -1902,24 +1870,26 @@ bufSize: the number of bytes in buf
.br
.br
-Returns 0 if OK, otherwise PI_BAD_REPEAT_CNT, PI_BAD_REPEAT_WID,
-PI_BAD_CHAIN_CMD, PI_TOO_MANY_COUNTS, or PI_BAD_WAVE_ID.
+Returns 0 if OK, otherwise PI_CHAIN_NESTING, PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD, PI_CHAIN_COUNTER,
+PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG, or PI_BAD_WAVE_ID.
.br
.br
-Each wave is transmitted in the order specified. A wave may only
-occur once per chain. Waves may be transmitted multiple times by
-using the repeat command. The repeat command specifies a wave id
-and a count. The wave id must occur earlier in the chain. All the
-waves between wave id and the repeat command are transmitted count
-times.
+Each wave is transmitted in the order specified. A wave may
+occur multiple times per chain.
.br
.br
-Repeat commands may not be nested. The minimum repeat count is 2.
-A maximum of 5 repeat commands is supported per chain.
+A blocks of waves may be transmitted multiple times by using
+the loop commands. The block is bracketed by loop start and
+end commands. Loops may be nested.
+
+.br
+
+.br
+Delays between waves may be added with the delay command.
.br
@@ -1929,13 +1899,24 @@ The following command codes are supported:
.br
.br
-Name Cmd & Data Meaning
+Name Cmd & Data Meaning
.br
-Repeat 255 wid C0 C1 C2 Repeat from wid count times
+Loop Start 255 0 Identify start of a wave block
.br
-count = C0 + C1*256 + C2*65536
+Loop Repeat 255 1 x y loop x + y*256 times
+
+.br
+Delay 255 2 x y delay x + y*256 microseconds
+
+.br
+
+.br
+
+.br
+The code is currently dimensioned to support a chain with roughly
+600 entries and 20 loop counters.
.br
@@ -1944,55 +1925,109 @@ count = C0 + C1*256 + C2*65536
.br
.EX
-The following examples assume that waves with ids 0 to 12 exist.
+#include
+.br
+#include
.br
.br
-// 0 255 0 57 0 0 (repeat 0 57 times)
+#define WAVES 5
.br
-status = gpioWaveChain((char []){0, 255, 0, 57, 0, 0}, 6);
+#define GPIO 4
.br
.br
-// 0 1 255 0 0 2 0 (repeat 0+1 512 times)
+int main(int argc, char *argv[])
.br
-status = gpioWaveChain((char []){0, 1, 255, 0, 0, 2, 0}, 7);
+{
+.br
+ int i, wid[WAVES];
.br
.br
-// 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
-.br
-status = gpioWaveChain((char []){0, 1, 255, 1, 0, 0, 1}, 7);
+ if (gpioInitialise()<0) return -1;
.br
.br
-// 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
-.br
-status = gpioWaveChain(
-.br
- (char []){0, 1, 2, 3, 255, 2, 13, 0, 0}, 9);
+ gpioSetMode(GPIO, PI_OUTPUT);
.br
.br
-// The following repeats 5 65793 times, transmits 6,
-.br
-// repeats 7+8 514 times, transmits 12,
-.br
-// repeats 9+11+10 197121 times.
-.br
-// 5 255 5 1 1 1 6 7 8 255 7 2 2 0 12 9 11 10 255 9 1 2 3
-.br
-char chain[] = {
-.br
- 5, 255, 5, 1, 1, 1,
-.br
- 6, 7, 8, 255, 7, 2, 2, 0,
-.br
- 12, 9, 11, 10, 255, 9, 1, 2, 3};
+ printf("start piscope, press return\n"); getchar();
.br
.br
-status = gpioWaveChain(chain, sizeof(chain));
+ for (i=0; i
*/
-/* pigpio version 34 */
+/* pigpio version 35 */
/* include ------------------------------------------------------- */
@@ -626,7 +626,10 @@ bit 0 READ_LAST_NOT_SET_ERROR
#define NORMAL_DMA (DMA_NO_WIDE_BURSTS | DMA_WAIT_RESP)
-#define TIMED_DMA(x) (DMA_DEST_DREQ | DMA_PERIPHERAL_MAPPING(x))
+#define TIMED_DMA(x) (DMA_DEST_DREQ | DMA_PERIPHERAL_MAPPING(x))
+
+#define PCM_TIMER (((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS)
+#define PWM_TIMER (((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS)
#define DBG_MIN_LEVEL 0
#define DBG_ALWAYS 0
@@ -669,6 +672,28 @@ bit 0 READ_LAST_NOT_SET_ERROR
#define CBS_PER_OPAGE 118
#define OOL_PER_OPAGE 79
+/*
+Wave Count Block
+
+Assumes two counters per block. Each counter 4 * 16 (16^4=65536)
+ 0 CB [13] 13*8 104 CBs for counter 0
+ 104 CB [13] 13*8 104 CBs for counter 1
+ 208 CB [60] 60*8 480 CBs reserved to construct wave
+ 688 OOL [60] 60*1 60 OOL reserved to construct wave
+ 748 OOL[136] 136*1 136 OOL for counter 0
+ 884 OOL[136] 136*1 136 OOL for counter 1
+1020 pad [4] 4*1 4 spare
+*/
+
+#define WCB_CNT_PER_PAGE 2
+#define WCB_COUNTERS (WCB_CNT_PER_PAGE * PI_WAVE_COUNT_PAGES)
+#define WCB_CNT_CBS 13
+#define WCB_CNT_OOL 68
+#define WCB_COUNTER_OOL (WCB_CNT_PER_PAGE * WCB_CNT_OOL)
+#define WCB_COUNTER_CBS (WCB_CNT_PER_PAGE * WCB_CNT_CBS)
+#define WCB_CHAIN_CBS 60
+#define WCB_CHAIN_OOL 60
+
#define CBS_PER_CYCLE ((PULSE_PER_CYCLE*3)+2)
#define NUM_CBS (CBS_PER_CYCLE * bufferCycles)
@@ -1086,9 +1111,8 @@ static rawWaveInfo_t waveInfo[PI_MAX_WAVES];
static wfRx_t wfRx[PI_MAX_USER_GPIO+1];
-static int waveOutBotCB = PI_WAVE_COUNTERS*CBS_PER_OPAGE;
-static int waveOutTopCB = NUM_WAVE_CBS;
-static int waveOutBotOOL = PI_WAVE_COUNTERS*OOL_PER_OPAGE;
+static int waveOutBotCB = PI_WAVE_COUNT_PAGES*CBS_PER_OPAGE;
+static int waveOutBotOOL = PI_WAVE_COUNT_PAGES*OOL_PER_OPAGE;
static int waveOutTopOOL = NUM_WAVE_OOL;
static int waveOutCount = 0;
@@ -1312,6 +1336,9 @@ static void initHWClk
static void initDMAgo(volatile uint32_t *dmaAddr, uint32_t cbAddr);
+int gpioWaveTxStart(unsigned wave_mode); /* deprecated */
+
+
/* ======================================================================= */
static char * myTimeStamp()
@@ -2461,19 +2488,6 @@ static uint32_t waveOOLPOadr(int pos)
}
-/* ----------------------------------------------------------------------- */
-
-static void waveCbOPrint(int pos)
-{
- rawCbs_t * p;
-
- p = rawWaveCBAdr(pos);
-
- fprintf(stderr, "i=%x s=%x d=%x len=%x s=%x nxt=%x\n",
- p->info, p->src, p->dst, p->length, p->stride, p->next);
-}
-
-
/* ----------------------------------------------------------------------- */
static void waveBitDelay
@@ -2501,20 +2515,42 @@ static void waveBitDelay
/* ----------------------------------------------------------------------- */
-static int errCBsOOL(int cb, int botOOL, int topOOL)
+static void waveCBsOOLs(int *numCBs, int *numBOOLs, int *numTOOLs)
{
- if (cb >= waveOutTopCB) return PI_TOO_MANY_CBS;
+ int numCB=0, numBOOL=0, numTOOL=0;
- if (botOOL >= topOOL) return PI_TOO_MANY_OOL;
+ unsigned i;
- return 0;
+ unsigned numWaves;
+
+ rawWave_t *waves;
+
+ numWaves = wfc[wfcur];
+ waves = wf [wfcur];
+
+ /* delay cb at start of DMA */
+
+ numCB++;
+
+ for (i=0; iinfo = NORMAL_DMA |
- DMA_DEST_DREQ |
- DMA_PERIPHERAL_MAPPING(2);
- p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(2);
+ p->dst = PCM_TIMER;
}
else
{
- p->info = NORMAL_DMA |
- DMA_DEST_DREQ |
- DMA_PERIPHERAL_MAPPING(5);
- p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(5);
+ p->dst = PWM_TIMER;
}
p->src = (uint32_t) (&dmaOBus[0]->periphData);
@@ -2564,8 +2594,6 @@ static int wave2Cbs(unsigned wave_mode)
{
if (waves[i].gpioOn)
{
- if ((status = errCBsOOL(botCB+1, botOOL+1, topOOL))) return status;
-
waveSetOOL(botOOL, waves[i].gpioOn);
p = rawWaveCBAdr(botCB++);
@@ -2579,8 +2607,6 @@ static int wave2Cbs(unsigned wave_mode)
if (waves[i].gpioOff)
{
- if ((status = errCBsOOL(botCB+1, botOOL+1, topOOL))) return status;
-
waveSetOOL(botOOL, waves[i].gpioOff);
p = rawWaveCBAdr(botCB++);
@@ -2594,8 +2620,6 @@ static int wave2Cbs(unsigned wave_mode)
if (waves[i].flags & WAVE_FLAG_READ)
{
- if ((status = errCBsOOL(botCB+1, botOOL, topOOL-1))) return status;
-
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
@@ -2607,8 +2631,6 @@ static int wave2Cbs(unsigned wave_mode)
if (waves[i].flags & WAVE_FLAG_TICK)
{
- if ((status = errCBsOOL(botCB+1, botOOL, topOOL-1))) return status;
-
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
@@ -2620,27 +2642,19 @@ static int wave2Cbs(unsigned wave_mode)
if (waves[i].usDelay)
{
- if ((status = errCBsOOL(botCB+1, botOOL, topOOL))) return status;
-
p = rawWaveCBAdr(botCB++);
/* use the secondary clock */
if (gpioCfg.clockPeriph != PI_CLOCK_PCM)
{
- p->info = NORMAL_DMA |
- DMA_DEST_DREQ |
- DMA_PERIPHERAL_MAPPING(2);
-
- p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(2);
+ p->dst = PCM_TIMER;
}
else
{
- p->info = NORMAL_DMA |
- DMA_DEST_DREQ |
- DMA_PERIPHERAL_MAPPING(5);
-
- p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(5);
+ p->dst = PWM_TIMER;
}
p->src = (uint32_t) (&dmaOBus[0]->periphData);
@@ -2656,113 +2670,15 @@ static int wave2Cbs(unsigned wave_mode)
else p->next = waveCbPOadr(repeatCB);
}
- status = botCB - waveOutBotCB;
+ status = botCB - *CB;
- waveOutBotCB = botCB;
- waveOutBotOOL = botOOL;
- waveOutTopOOL = topOOL;
+ *CB = botCB;
+ *BOOL = botOOL;
+ *TOOL = topOOL;
return status;
}
-/* ----------------------------------------------------------------------- */
-
-static uint32_t waveGetIn(int page, int slot)
-{
- return (dmaOVirt[page]->OOL[slot]);
-}
-
-static void waveSetIn(int page, int slot, uint32_t value)
-{
- dmaOVirt[page]->OOL[slot] = value;
-}
-
-static uint32_t myWaveOOLPOadr(int page, int slot)
-{
- return (uint32_t) &dmaOBus[page]->OOL[slot];
-}
-
-static void waveCount(
- unsigned counter,
- unsigned blklen,
- unsigned blocks,
- unsigned count,
- uint32_t repeat,
- uint32_t next)
-{
- rawCbs_t *p=NULL;
-
- int b, baseCB, dig;
- uint32_t nxt;
-
- int botCB;
-
- botCB = counter * CBS_PER_OPAGE;
-
- baseCB = botCB;
-
- /* set up all the OOLs */
- for (b=0; b < (blocks*(blklen+1)); b++) waveSetIn(counter, b, repeat);
-
- for (b=0; binfo = NORMAL_DMA;
-
- p->src = myWaveOOLPOadr(counter, b*(blklen+1));
- p->dst = (waveCbPOadr(botCB+1) + 20);
-
- p->length = 4;
- p->next = waveCbPOadr(botCB);
-
- /* copy BOTTOM to TOP */
-
- p = rawWaveCBAdr(botCB++);
-
- p->info = NORMAL_DMA;
-
- p->src = myWaveOOLPOadr(counter, b*(blklen+1));
- p->dst = myWaveOOLPOadr(counter, (b*(blklen+1))+blklen);
-
- p->length = 4;
- p->next = waveCbPOadr(botCB);
-
- /* shift all down one */
-
- p = rawWaveCBAdr(botCB++);
-
- p->info = NORMAL_DMA|DMA_SRC_INC|DMA_DEST_INC;
-
- p->src = myWaveOOLPOadr(counter, ((b*(blklen+1))+1));
- p->dst = myWaveOOLPOadr(counter, ((b*(blklen+1))+0));
-
- p->length = blklen*4;
- p->next = repeat;
- }
-
- b = 0;
-
- while (count && (binfo = NORMAL_DMA | TIMED_DMA(2);
- p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(2);
+ p->dst = PCM_TIMER;
}
else
{
- p->info = NORMAL_DMA | TIMED_DMA(5);
- p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(5);
+ p->dst = PWM_TIMER;
}
p->src = dmaPwmDataAdr(b%DMAI_PAGES);
@@ -7463,9 +7379,6 @@ void gpioTerminate(void)
static void switchFunctionOff(unsigned gpio)
{
- unsigned clock, pwm;
- int cctl[] = {CLK_GP0_CTL, CLK_GP1_CTL, CLK_GP2_CTL};
-
switch (gpioInfo[gpio].is)
{
case GPIO_SERVO:
@@ -7481,17 +7394,12 @@ static void switchFunctionOff(unsigned gpio)
break;
case GPIO_HW_CLK:
- /* switch hardware clock off */
- clock = (clkDef[gpio] >> 4) & 3;
- clkReg[cctl[clock]] = CLK_PASSWD | CLK_CTL_KILL;
+ /* No longer disable clock hardware, doing that was a bug. */
gpioInfo[gpio].width = 0;
break;
case GPIO_HW_PWM:
- /* switch hardware PWM off */
- pwm = (PWMDef[gpio] >> 4) & 3;
- if (pwm == 0) pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN1);
- else pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN2);
+ /* No longer disable PWM hardware, doing that was a bug. */
gpioInfo[gpio].width = 0;
break;
}
@@ -7499,14 +7407,18 @@ static void switchFunctionOff(unsigned gpio)
static void stopHardwarePWM(void)
{
- int i;
+ unsigned i, pwm;
for (i=0; i<= PI_MAX_GPIO; i++)
{
if (gpioInfo[i].is == GPIO_HW_PWM)
{
- switchFunctionOff(i);
+ pwm = (PWMDef[i] >> 4) & 3;
+ if (pwm == 0) pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN1);
+ else pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN2);
+
+ gpioInfo[i].width = 0;
gpioInfo[i].is = GPIO_UNDEFINED;
}
}
@@ -7953,9 +7865,8 @@ int gpioWaveClear(void)
wfStats.pulses = 0;
wfStats.cbs = 0;
- waveOutBotCB = PI_WAVE_COUNTERS*CBS_PER_OPAGE;
- waveOutTopCB = NUM_WAVE_CBS;
- waveOutBotOOL = PI_WAVE_COUNTERS*OOL_PER_OPAGE;
+ waveOutBotCB = PI_WAVE_COUNT_PAGES*CBS_PER_OPAGE;
+ waveOutBotOOL = PI_WAVE_COUNT_PAGES*OOL_PER_OPAGE;
waveOutTopOOL = NUM_WAVE_OOL;
waveOutCount = 0;
@@ -8041,7 +7952,8 @@ int gpioWaveAddSerial
if ((baud < PI_WAVE_MIN_BAUD) || (baud > PI_WAVE_MAX_BAUD))
SOFT_ERROR(PI_BAD_WAVE_BAUD, "bad baud rate (%d)", baud);
- if ((data_bits < PI_MIN_WAVE_DATABITS) || (data_bits > PI_MAX_WAVE_DATABITS))
+ if ((data_bits < PI_MIN_WAVE_DATABITS) ||
+ (data_bits > PI_MAX_WAVE_DATABITS))
SOFT_ERROR(PI_BAD_DATABITS, "bad number of databits (%d)", data_bits);
if ((stop_bits < PI_MIN_WAVE_HALFSTOPBITS) ||
@@ -8286,7 +8198,9 @@ int rawWaveAddSPI(
int gpioWaveCreate(void)
{
- int cb;
+ int i, wid;
+ int numCB, numBOOL, numTOOL;
+ int CB, BOOL, TOOL;
DBG(DBG_USER, "");
@@ -8294,22 +8208,86 @@ int gpioWaveCreate(void)
if (wfc[wfcur] == 0) return PI_EMPTY_WAVEFORM;
- if (waveOutCount < PI_MAX_WAVES)
+ /* What resources are needed? */
+
+ waveCBsOOLs(&numCB, &numBOOL, &numTOOL);
+
+ wid = -1;
+
+ /* Is there an exact fit with a deleted wave. */
+
+ for (i=0; i= NUM_WAVE_CBS)
+ return PI_TOO_MANY_CBS;
+
+ if ((numBOOL+waveOutBotOOL) >= (waveOutTopOOL-numTOOL))
+ return PI_TOO_MANY_OOL;
+
+ if (wid >= PI_MAX_WAVES)
+ return PI_NO_WAVEFORM_ID;
+
+ wid = waveOutCount++;
+
+ waveInfo[wid].botCB = waveOutBotCB;
+ waveInfo[wid].topCB = waveOutBotCB + numCB -1;
+ waveInfo[wid].botOOL = waveOutBotOOL;
+ waveInfo[wid].topOOL = waveOutTopOOL;
+ waveInfo[wid].numCB = numCB;
+ waveInfo[wid].numBOOL = numBOOL;
+ waveInfo[wid].numTOOL = numTOOL;
+
+ waveOutBotCB += numCB;
+ waveOutBotOOL += numBOOL;
+ waveOutTopOOL -= numTOOL;
+ }
+
+ /* Must be room if got this far. */
+
+ CB = waveInfo[wid].botCB;
+ BOOL = waveInfo[wid].botOOL;
+ TOOL = waveInfo[wid].topOOL;
+
+ wave2Cbs(PI_WAVE_MODE_ONE_SHOT, &CB, &BOOL, &TOOL);
+
+ /* Sanity check. */
+
+ if ( (numCB != (CB-waveInfo[wid].botCB)) ||
+ (numBOOL != (BOOL-waveInfo[wid].botOOL)) ||
+ (numTOOL != (waveInfo[wid].topOOL-TOOL)) )
+ {
+ DBG(0, "ERROR wid=%d CBs %d=%d BOOL %d=%d TOOL %d=%d", wid,
+ numCB, CB-waveInfo[wid].botCB,
+ numBOOL, BOOL-waveInfo[wid].botOOL,
+ numTOOL, waveInfo[wid].topOOL-TOOL);
+ }
+
+ waveInfo[wid].deleted = 0;
+
+ /* Consume waves. */
+
+ wfc[0] = 0;
+ wfc[1] = 0;
+ wfc[2] = 0;
+
+ wfcur = 0;
+
+ return wid;
}
/* ----------------------------------------------------------------------- */
@@ -8320,14 +8298,23 @@ int gpioWaveDelete(unsigned wave_id)
CHECK_INITED;
- if (wave_id >= waveOutCount)
+ if ((wave_id >= waveOutCount) || waveInfo[wave_id].deleted)
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;
+ waveInfo[wave_id].deleted = 1;
- waveOutCount = wave_id;
+ if (wave_id == (waveOutCount-1))
+ {
+ /* top wave deleted, garbage collect any other deleted waves */
+
+ while ((wave_id > 0) && (waveInfo[wave_id-1].deleted)) --wave_id;
+
+ waveOutBotCB = waveInfo[wave_id].botCB;
+ waveOutBotOOL = waveInfo[wave_id].botOOL;
+ waveOutTopOOL = waveInfo[wave_id].topOOL;
+
+ waveOutCount = wave_id;
+ }
return 0;
}
@@ -8336,53 +8323,11 @@ int gpioWaveDelete(unsigned wave_id)
int gpioWaveTxStart(unsigned wave_mode)
{
- /* This function is deprecated and will be removed. */
-
- int firstCB=PI_WAVE_COUNTERS*CBS_PER_OPAGE;
- int numCBs, i;
-
- DBG(DBG_USER, "wave_mode=%d", wave_mode);
+ /* This function is deprecated and has been removed. */
CHECK_INITED;
- if (wave_mode > PI_WAVE_MODE_REPEAT)
- SOFT_ERROR(PI_BAD_WAVE_MODE, "bad wave mode (%d)", wave_mode);
-
- if (wfc[wfcur] == 0) return 0;
-
- if (!waveClockInited)
- {
- stopHardwarePWM();
- initClock(0); /* initialise secondary clock */
- waveClockInited = 1;
- }
-
- dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
-
- dmaOut[DMA_CONBLK_AD] = 0;
-
- waveOutBotCB = firstCB;
- waveOutTopCB = NUM_WAVE_CBS;
- waveOutBotOOL = PI_WAVE_COUNTERS*OOL_PER_OPAGE;
- waveOutTopOOL = NUM_WAVE_OOL;
-
- waveOutCount = 0;
-
- numCBs = wave2Cbs(wave_mode);
-
- if (numCBs > 0)
- {
- if (gpioCfg.dbgLevel >= DBG_SLOW_TICK)
- {
- fprintf(stderr, "*** OUTPUT DMA CONTROL BLOCKS ***\n");
- for (i=0; i= waveOutCount)
+ if ((wave_id >= waveOutCount) || waveInfo[wave_id].deleted)
SOFT_ERROR(PI_BAD_WAVE_ID, "bad wave id (%d)", wave_id);
if (wave_mode > PI_WAVE_MODE_REPEAT)
@@ -8425,16 +8370,201 @@ int gpioWaveTxSend(unsigned wave_id, unsigned wave_mode)
return (waveInfo[wave_id].topCB - waveInfo[wave_id].botCB) + 1;
}
+
/* ----------------------------------------------------------------------- */
+static int chainGetCB(int n)
+{
+ int block, index;
+
+ if (n < (WCB_CHAIN_CBS * PI_WAVE_COUNT_PAGES))
+ {
+ block = n / WCB_CHAIN_CBS;
+ index = n % WCB_CHAIN_CBS;
+ return (block*CBS_PER_OPAGE) + WCB_COUNTER_CBS + index;
+ }
+ return -1;
+}
+
+static void chainSetVal(int n, uint32_t val)
+{
+ int block, index;
+ uint32_t *p;
+
+ if (n < (WCB_CHAIN_OOL * PI_WAVE_COUNT_PAGES))
+ {
+ block = n / WCB_CHAIN_OOL;
+ index = n % WCB_CHAIN_OOL;
+ p = (uint32_t *) dmaOVirt[block] + (WCB_COUNTER_CBS+WCB_CHAIN_CBS) * 8;
+ p[index] = val;
+ }
+}
+
+static uint32_t chainGetValPadr(int n)
+{
+ int block, index;
+ uint32_t *p;
+
+ if (n < (WCB_CHAIN_OOL * PI_WAVE_COUNT_PAGES))
+ {
+ block = n / WCB_CHAIN_OOL;
+ index = n % WCB_CHAIN_OOL;
+ p = (uint32_t *) dmaOBus[block] + (WCB_COUNTER_CBS+WCB_CHAIN_CBS) * 8;
+ return (uint32_t) (p + index);
+ }
+ return 0;
+}
+
+static uint32_t chainGetCntVal(int counter, int slot)
+{
+ uint32_t *p;
+ int page, offset;
+ page = counter / 2;
+ offset = (counter % 2 ? WCB_COUNTER_OOL : 0);
+ p = (uint32_t *) dmaOVirt[page] + (WCB_COUNTER_CBS+WCB_CHAIN_CBS) * 8;
+ return p[WCB_CHAIN_OOL+ offset + slot];
+}
+
+static void chainSetCntVal(int counter, int slot, uint32_t value)
+{
+ uint32_t *p;
+ int page, offset;
+ page = counter / 2;
+ offset = (counter % 2 ? WCB_COUNTER_OOL : 0);
+ p = (uint32_t *) dmaOVirt[page] + (WCB_COUNTER_CBS+WCB_CHAIN_CBS) * 8;
+ p[WCB_CHAIN_OOL + offset + slot] = value;
+}
+
+static uint32_t chainGetCntValPadr(int counter, int slot)
+{
+ uint32_t *p;
+ int page, offset;
+ page = counter / 2;
+ offset = (counter % 2 ? WCB_COUNTER_OOL : 0);
+ p = (uint32_t *) dmaOBus[page] + (WCB_COUNTER_CBS+WCB_CHAIN_CBS) * 8;
+ return (uint32_t)(p + WCB_CHAIN_OOL + offset + slot);
+}
+
+static int chainGetCntCB(int counter)
+{
+ int page, offset;
+ page = counter / 2;
+ offset = (counter % 2 ? WCB_CNT_CBS : 0);
+ return ((page * CBS_PER_OPAGE) + offset);
+}
+
+static void chainMakeCounter(
+ unsigned counter,
+ unsigned blklen,
+ unsigned blocks,
+ unsigned count,
+ uint32_t repeat,
+ uint32_t next)
+{
+ rawCbs_t *p=NULL;
+
+ int b, baseCB, dig;
+ uint32_t nxt;
+
+ int botCB;
+
+ botCB = chainGetCntCB(counter);
+
+ baseCB = botCB;
+
+ /* set up all the OOLs */
+ for (b=0; b < (blocks*(blklen+1)); b++) chainSetCntVal(counter, b, repeat);
+
+ for (b=0; binfo = NORMAL_DMA;
+
+ p->src = chainGetCntValPadr(counter, b*(blklen+1));
+ p->dst = (waveCbPOadr(botCB+1) + 20);
+
+ p->length = 4;
+ p->next = waveCbPOadr(botCB);
+
+ /* copy BOTTOM to TOP */
+
+ p = rawWaveCBAdr(botCB++);
+
+ p->info = NORMAL_DMA;
+
+ p->src = chainGetCntValPadr(counter, b*(blklen+1));
+ p->dst = chainGetCntValPadr(counter, (b*(blklen+1))+blklen);
+
+ p->length = 4;
+ p->next = waveCbPOadr(botCB);
+
+ /* shift all down one */
+
+ p = rawWaveCBAdr(botCB++);
+
+ p->info = NORMAL_DMA|DMA_SRC_INC|DMA_DEST_INC;
+
+ p->src = chainGetCntValPadr(counter, ((b*(blklen+1))+1));
+ p->dst = chainGetCntValPadr(counter, ((b*(blklen+1))+0));
+
+ p->length = blklen*4;
+ p->next = repeat;
+ }
+
+ /* reset the counter */
+
+ p = rawWaveCBAdr(botCB);
+
+ p->info = NORMAL_DMA|DMA_SRC_INC|DMA_DEST_INC;
+
+ p->src = chainGetCntValPadr(counter, blocks*(blklen+1));
+ p->dst = chainGetCntValPadr(counter, 0);
+
+ p->length = blocks*(blklen+1)*4;
+ p->next = next;
+
+ b = 0;
+
+ while (count && (binfo = NORMAL_DMA | TIMED_DMA(2);
+ p->dst = PCM_TIMER;
+ }
+ else
+ {
+ p->info = NORMAL_DMA | TIMED_DMA(5);
+ p->dst = PWM_TIMER;
+ }
+
+ p->src = (uint32_t) (&dmaOBus[0]->periphData);
+ p->length = 4 * 20 / PI_WF_MICROS; /* 20 micros delay */
+ p->next = waveCbPOadr(chainGetCB(cb));
counters = 0;
wid = -1;
- lastCB = -1;
- firstCB = -1;
i = 0;
@@ -8464,92 +8611,183 @@ int gpioWaveChain(char *buf, unsigned bufSize)
{
wid = (unsigned)buf[i];
- if (wid == 255) /* repeat wave command */
+ if (wid == 255) /* wave command */
{
- if (counters < PI_WAVE_COUNTERS)
+ if ((i+2) > bufSize)
+ SOFT_ERROR(PI_BAD_CHAIN_CMD,
+ "incomplete chain command (at %d)", i);
+
+ cmd = buf[i+1];
+
+ if (cmd == 0) /* loop begin */
{
- if ((i+4) < bufSize)
- {
- rwid = buf[i+1];
- if ((i+5) < bufSize)
- {
- nwid = buf[i+5];
- if (nwid < waveOutCount)
- next = waveCbPOadr(1+waveInfo[nwid].botCB);
- else next = 0; /* error, will be picked up later */
- }
- else next = 0;
- if (used[rwid] == counters)
- {
- repeat = waveCbPOadr(1+waveInfo[rwid].botCB);
+ if (stk_lev >= (sizeof(stk_pos)/sizeof(int)))
+ SOFT_ERROR(PI_CHAIN_NESTING,
+ "chain counters nested too deep (at %d)", i);
- cycles = (unsigned)buf[i+2] +
- ((unsigned)buf[i+3]<<8) +
- ((unsigned)buf[i+4]<<16);
-
- i+=4;
-
- if ((cycles > 1) && (cycles < PI_MAX_WAVE_CYCLES))
- {
- --cycles;
-
- waveCount(counters, blklen, blocks, cycles, repeat, next);
-
- p = rawWaveCBAdr(lastCB);
-
- lastCB = -1;
-
- p->next = waveCbPOadr(counters * CBS_PER_OPAGE);
-
- counters++;
- }
- else SOFT_ERROR(PI_BAD_REPEAT_CNT,
- "bad chain repeat count (%d)", cycles);
- }
- else SOFT_ERROR(PI_BAD_REPEAT_WID,
- "bad chain repeat wave (%d)", rwid);
- }
- else SOFT_ERROR(PI_BAD_CHAIN_CMD,
- "bad chain command (at char %d)", i);
+ stk_pos[stk_lev++] = cb;
+ i += 2;
}
- else SOFT_ERROR(PI_TOO_MANY_COUNTS,
- "too many chain counters (at char %d)", i);
+ else if (cmd == 1) /* loop end */
+ {
+ if (counters >= WCB_COUNTERS)
+ SOFT_ERROR(PI_CHAIN_COUNTER,
+ "too many chain counters (at %d)", i);
+
+ if ((i+4) > bufSize)
+ SOFT_ERROR(PI_BAD_CHAIN_CMD,
+ "incomplete chain command (at %d)", i);
+
+ loop = 0;
+ if (--stk_lev >= 0) loop = stk_pos[stk_lev];
+
+ if ((loop < 1) || (loop == cb))
+ SOFT_ERROR(PI_BAD_CHAIN_LOOP,
+ "empty chain loop (at %d)", i);
+
+ cycles = ((unsigned)buf[i+3] << 8) + (unsigned)buf[i+2];
+
+ i += 4;
+
+ if (cycles > PI_MAX_WAVE_CYCLES)
+ SOFT_ERROR(PI_CHAIN_LOOP_CNT,
+ "bad chain loop count (%d)", cycles);
+
+ if (cycles == 0)
+ {
+ /* Skip the complete loop block. Change
+ the next pointing to the start of the
+ loop block to the current cb.
+ */
+ p = rawWaveCBAdr(chainGetCB(loop));
+ p->next = waveCbPOadr(chainGetCB(cb));
+ }
+ else if (cycles == 1)
+ {
+ /* Nothing to do, no need for a counter. */
+ }
+ else
+ {
+ chaincb = chainGetCB(cb++);
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
+
+ p = rawWaveCBAdr(chaincb);
+
+ repeat = waveCbPOadr(chainGetCB(loop));
+
+ /* Need to check next cb as well. */
+
+ chaincb = chainGetCB(cb);
+
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
+
+ next = waveCbPOadr(chainGetCB(cb));
+
+ /* dummy src and dest */
+ p->info = NORMAL_DMA;
+ p->src = (uint32_t) (&dmaOBus[0]->periphData);
+ p->dst = (uint32_t) (&dmaOBus[0]->periphData);
+ p->length = 4;
+ p->next = waveCbPOadr(chainGetCntCB(counters));
+
+ chainMakeCounter(counters, blklen, blocks,
+ cycles-1, repeat, next);
+
+ counters++;
+ }
+ loop = -1;
+ }
+ else if (cmd == 2) /* delay us */
+ {
+ if ((i+4) > bufSize)
+ SOFT_ERROR(PI_BAD_CHAIN_CMD,
+ "incomplete chain command (at %d)", i);
+
+ cycles = ((unsigned)buf[i+3] << 8) + (unsigned)buf[i+2];
+
+ i += 4;
+
+ if (cycles > PI_MAX_WAVE_DELAY)
+ SOFT_ERROR(PI_BAD_CHAIN_DELAY,
+ "bad chain delay micros (%d)", cycles);
+
+ if (cycles)
+ {
+ chaincb = chainGetCB(cb++);
+
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
+
+ p = rawWaveCBAdr(chaincb);
+
+ /* use the secondary clock */
+
+ if (gpioCfg.clockPeriph != PI_CLOCK_PCM)
+ {
+ p->info = NORMAL_DMA | TIMED_DMA(2);
+ p->dst = PCM_TIMER;
+ }
+ else
+ {
+ p->info = NORMAL_DMA | TIMED_DMA(5);
+ p->dst = PWM_TIMER;
+ }
+
+ p->src = (uint32_t) (&dmaOBus[0]->periphData);
+ p->length = 4 * cycles / PI_WF_MICROS;
+ p->next = waveCbPOadr(chainGetCB(cb));
+ }
+ }
+ else
+ SOFT_ERROR(PI_BAD_CHAIN_CMD,
+ "unknown chain command (255 %d)", cmd);
}
- else if (wid >= waveOutCount)
+ else if ((wid >= waveOutCount) || waveInfo[wid].deleted)
SOFT_ERROR(PI_BAD_WAVE_ID, "undefined wave (%d)", wid);
else
{
- if (used[wid] == 255)
- {
- used[wid] = counters;
+ chaincb = chainGetCB(cb++);
- if (firstCB < 0) firstCB = waveInfo[wid].botCB;
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
- if (lastCB >= 0)
- {
- p = rawWaveCBAdr(lastCB);
+ p = rawWaveCBAdr(chaincb);
- p->next = waveCbPOadr(1+waveInfo[wid].botCB);
- }
- lastCB = waveInfo[wid].topCB;
- }
- else SOFT_ERROR(PI_REUSED_WID,
- "wave already used in chain (%d)", wid);
+ chaincb = chainGetCB(cb);
+
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
+
+ chainSetVal(cb-1, waveCbPOadr(chaincb));
+
+ /* patch next of wid topCB to next cb */
+
+ p->info = NORMAL_DMA;
+ p->src = chainGetValPadr(cb-1); /* this next */
+ p->dst = waveCbPOadr(waveInfo[wid].topCB) + 20; /* wid next */
+ p->length = 4;
+ p->next = waveCbPOadr(waveInfo[wid].botCB+1);
+
+ i += 1;
}
- i++;
}
- if (firstCB >= 0)
- {
- if (lastCB >= 0)
- {
- p = rawWaveCBAdr(lastCB);
+ chaincb = chainGetCB(cb++);
- p->next = 0;
- }
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
- initDMAgo((uint32_t *)dmaOut, waveCbPOadr(firstCB));
- }
+ p = rawWaveCBAdr(chaincb);
+
+ p->info = NORMAL_DMA;
+ p->src = (uint32_t) (&dmaOBus[0]->periphData);
+ p->dst = (uint32_t) (&dmaOBus[0]->periphData);
+ p->length = 4;
+ p->next = 0;
+
+ initDMAgo((uint32_t *)dmaOut, waveCbPOadr(chainGetCB(0)));
return 0;
}
diff --git a/pigpio.h b/pigpio.h
index f5f12a6..a13d3be 100644
--- a/pigpio.h
+++ b/pigpio.h
@@ -31,7 +31,7 @@ For more information, please refer to
#include
#include
-#define PIGPIO_VERSION 34
+#define PIGPIO_VERSION 35
/*TEXT
@@ -197,7 +197,7 @@ gpioWaveAddGeneric Adds a series of pulses to the waveform
gpioWaveAddSerial Adds serial data to the waveform
gpioWaveCreate Creates a waveform from added data
-gpioWaveDelete Deletes one or more waveforms
+gpioWaveDelete Deletes a waveform
gpioWaveTxSend Transmits a waveform
@@ -218,8 +218,6 @@ gpioWaveGetCbs Length in control blocks of the current waveform
gpioWaveGetHighCbs Length of longest waveform so far
gpioWaveGetMaxCbs Absolute maximum allowed control blocks
-gpioWaveTxStart Creates/transmits a waveform (DEPRECATED)
-
I2C
i2cOpen Opens an I2C device
@@ -383,12 +381,31 @@ typedef struct
uint32_t flags;
} rawWave_t;
+/*
+CBs are used in order from the lowest numbered CB up to
+the maximum NUM_WAVE_CBS.
+
+OOLS are used from the bottom climbing up and from
+the top climbing down.
+
+The gpio on and off settings climb up from the bottom (botOOL/numBOOL).
+
+The level and tick read values are stored in descending locations
+from the top (topOOL/numTOOL).
+*/
+
typedef struct
{
uint16_t botCB; /* first CB used by wave */
uint16_t topCB; /* last CB used by wave */
- uint16_t botOOL; /* last OOL used by wave */
- uint16_t topOOL; /* first OOL used by wave */
+ uint16_t botOOL; /* first bottom OOL used by wave */
+ /* botOOL to botOOL + numBOOL -1 are in use */
+ uint16_t topOOL; /* last top OOL used by wave */
+ /* topOOL - numTOOL to topOOL are in use.*/
+ uint16_t deleted;
+ uint16_t numCB;
+ uint16_t numBOOL;
+ uint16_t numTOOL;
} rawWaveInfo_t;
typedef struct
@@ -549,10 +566,12 @@ typedef void *(gpioThreadFunc_t) (void *);
#define PI_WAVE_MAX_MICROS (30 * 60 * 1000000) /* half an hour */
-#define PI_MAX_WAVES 250
-//#define PI_MAX_WAVE_CYCLES 537824
-#define PI_MAX_WAVE_CYCLES 16777216
-#define PI_WAVE_COUNTERS 5
+#define PI_MAX_WAVES 250
+
+#define PI_MAX_WAVE_CYCLES 65535
+#define PI_MAX_WAVE_DELAY 65535
+
+#define PI_WAVE_COUNT_PAGES 10
/* wave tx mode */
@@ -1511,8 +1530,9 @@ D*/
int gpioWaveCreate(void);
/*D
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.
+calls to the [*gpioWaveAdd**] functions. Upon success a wave id
+greater than or equal to 0 is returned, otherwise PI_EMPTY_WAVEFORM,
+PI_TOO_MANY_CBS, PI_TOO_MANY_OOL, or PI_NO_WAVEFORM_ID.
The data provided by the [*gpioWaveAdd**] functions is consumed by this
function.
@@ -1564,8 +1584,7 @@ D*/
/*F*/
int gpioWaveDelete(unsigned wave_id);
/*D
-This function deletes all created waveforms with ids greater than or
-equal to wave_id.
+This function deletes the waveform with id wave_id.
. .
wave_id: >=0, as returned by [*gpioWaveCreate*]
@@ -1577,26 +1596,6 @@ Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
D*/
-/*F*/
-int gpioWaveTxStart(unsigned wave_mode); /* DEPRECATED */
-/*D
-This function creates and then transmits a waveform. The mode
-determines whether the waveform is sent once or cycles endlessly.
-
-NOTE: Any hardware PWM started by [*gpioHardwarePWM*] will be cancelled.
-
-. .
-wave_mode: 0 (PI_WAVE_MODE_ONE_SHOT), 1 (PI_WAVE_MODE_REPEAT)
-. .
-
-This function is deprecated and should no longer be used. Use
-[*gpioWaveCreate*] and [*gpioWaveTxSend*] instead.
-
-Returns the number of DMA control blocks in the waveform if OK,
-otherwise PI_BAD_WAVE_MODE.
-D*/
-
-
/*F*/
int gpioWaveTxSend(unsigned wave_id, unsigned wave_mode);
/*D
@@ -1623,7 +1622,7 @@ This function transmits a chain of waveforms.
NOTE: Any hardware PWM started by [*gpioHardwarePWM*] will be cancelled.
The waves to be transmitted are specified by the contents of buf
-which contains an ordered list of wave_ids and optional command
+which contains an ordered list of [*wave_id*]s and optional command
codes and related data.
. .
@@ -1631,51 +1630,81 @@ codes and related data.
bufSize: the number of bytes in buf
. .
-Returns 0 if OK, otherwise PI_BAD_REPEAT_CNT, PI_BAD_REPEAT_WID,
-PI_BAD_CHAIN_CMD, PI_TOO_MANY_COUNTS, or PI_BAD_WAVE_ID.
+Returns 0 if OK, otherwise PI_CHAIN_NESTING, PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD, PI_CHAIN_COUNTER,
+PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG, or PI_BAD_WAVE_ID.
-Each wave is transmitted in the order specified. A wave may only
-occur once per chain. Waves may be transmitted multiple times by
-using the repeat command. The repeat command specifies a wave id
-and a count. The wave id must occur earlier in the chain. All the
-waves between wave id and the repeat command are transmitted count
-times.
+Each wave is transmitted in the order specified. A wave may
+occur multiple times per chain.
-Repeat commands may not be nested. The minimum repeat count is 2.
-A maximum of 5 repeat commands is supported per chain.
+A blocks of waves may be transmitted multiple times by using
+the loop commands. The block is bracketed by loop start and
+end commands. Loops may be nested.
+
+Delays between waves may be added with the delay command.
The following command codes are supported:
-Name @ Cmd & Data @ Meaning
-Repeat @ 255 wid C0 C1 C2 @ Repeat from wid count times
-count = C0 + C1*256 + C2*65536
+Name @ Cmd & Data @ Meaning
+Loop Start @ 255 0 @ Identify start of a wave block
+Loop Repeat @ 255 1 x y @ loop x + y*256 times
+Delay @ 255 2 x y @ delay x + y*256 microseconds
+
+The code is currently dimensioned to support a chain with roughly
+600 entries and 20 loop counters.
...
-The following examples assume that waves with ids 0 to 12 exist.
+#include
+#include
-// 0 255 0 57 0 0 (repeat 0 57 times)
-status = gpioWaveChain((char []){0, 255, 0, 57, 0, 0}, 6);
+#define WAVES 5
+#define GPIO 4
-// 0 1 255 0 0 2 0 (repeat 0+1 512 times)
-status = gpioWaveChain((char []){0, 1, 255, 0, 0, 2, 0}, 7);
+int main(int argc, char *argv[])
+{
+ int i, wid[WAVES];
-// 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
-status = gpioWaveChain((char []){0, 1, 255, 1, 0, 0, 1}, 7);
+ if (gpioInitialise()<0) return -1;
-// 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
-status = gpioWaveChain(
- (char []){0, 1, 2, 3, 255, 2, 13, 0, 0}, 9);
+ gpioSetMode(GPIO, PI_OUTPUT);
-// The following repeats 5 65793 times, transmits 6,
-// repeats 7+8 514 times, transmits 12,
-// repeats 9+11+10 197121 times.
-// 5 255 5 1 1 1 6 7 8 255 7 2 2 0 12 9 11 10 255 9 1 2 3
-char chain[] = {
- 5, 255, 5, 1, 1, 1,
- 6, 7, 8, 255, 7, 2, 2, 0,
- 12, 9, 11, 10, 255, 9, 1, 2, 3};
+ printf("start piscope, press return\n"); getchar();
-status = gpioWaveChain(chain, sizeof(chain));
+ for (i=0; i=0) if OK.
+ Returns a wave id (>=0) if OK, otherwise PI_EMPTY_WAVEFORM,
+ PI_TOO_MANY_CBS, PI_TOO_MANY_OOL, or PI_NO_WAVEFORM_ID.
The data provided by the [*wave_add_**] functions is consumed by
this function.
@@ -1864,40 +1867,33 @@ class pi():
def wave_delete(self, wave_id):
"""
- Deletes all created waveforms with ids greater than or equal
- to wave_id.
+ This function deletes the waveform with id wave_id.
wave_id:= >=0 (as returned by a prior call to [*wave_create*]).
Wave ids are allocated in order, 0, 1, 2, etc.
...
- pi.wave_delete(6) # delete all waves with id 6 or greater
+ pi.wave_delete(6) # delete waveform with id 6
- pi.wave_delete(0) # delete all waves
+ pi.wave_delete(0) # delete waveform with id 0
...
"""
return _u2i(_pigpio_command(self.sl, _PI_CMD_WVDEL, wave_id, 0))
def wave_tx_start(self): # DEPRECATED
"""
- This function is deprecated and will be removed.
+ This function is deprecated and has been removed.
Use [*wave_create*]/[*wave_send_**] instead.
-
- NOTE: Any hardware PWM started by [*hardware_PWM*] will
- be cancelled.
"""
return _u2i(_pigpio_command(self.sl, _PI_CMD_WVGO, 0, 0))
def wave_tx_repeat(self): # DEPRECATED
"""
- This function is deprecated and will be removed.
+ This function is deprecated and has beeen removed.
Use [*wave_create*]/[*wave_send_**] instead.
-
- NOTE: Any hardware PWM started by [*hardware_PWM*] will
- be cancelled.
"""
return _u2i(_pigpio_command(self.sl, _PI_CMD_WVGOR, 0, 0))
@@ -1975,58 +1971,84 @@ class pi():
"""
This function transmits a chain of waveforms.
- NOTE: Any hardware PWM started by [*hardware_PWM*] will
- be cancelled.
+ NOTE: Any hardware PWM started by [*hardware_PWM*]
+ will be cancelled.
- The waves to be transmitted are specified by the contents of
- data which contains an ordered list of wave_ids and optional
- command codes and related data.
+ The waves to be transmitted are specified by the contents
+ of data which contains an ordered list of [*wave_id*]s
+ and optional command codes and related data.
- data:= contains the wave_ids and optional command codes
+ Returns 0 if OK, otherwise PI_CHAIN_NESTING,
+ PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD,
+ PI_CHAIN_COUNTER, PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG,
+ or PI_BAD_WAVE_ID.
- Returns 0 if OK, otherwise PI_BAD_REPEAT_CNT, PI_BAD_REPEAT_WID,
- PI_BAD_CHAIN_CMD, PI_TOO_MANY_COUNTS, or PI_BAD_WAVE_ID.
+ Each wave is transmitted in the order specified. A wave
+ may occur multiple times per chain.
- Each wave is transmitted in the order specified. A wave may
- only occur once per chain. Waves may be transmitted multiple
- times by using the repeat command. The repeat command
- specifies a wave id and a count. The wave id must occur
- earlier in the chain. All the waves between wave id and the
- repeat command are transmitted count times.
+ A blocks of waves may be transmitted multiple times by
+ using the loop commands. The block is bracketed by loop
+ start and end commands. Loops may be nested.
- Repeat commands may not be nested. The minimum repeat
- count is 2. A maximum of 5 repeat commands is supported
- per chain.
+ Delays between waves may be added with the delay command.
The following command codes are supported:
- Name @ Cmd & Data @ Meaning
- Repeat @ 255 wid C0 C1 C2 @ Repeat from wid count times
- count = C0 + C1*256 + C2*65536
+ Name @ Cmd & Data @ Meaning
+ Loop Start @ 255 0 @ Identify start of a wave block
+ Loop Repeat @ 255 1 x y @ loop x + y*256 times
+ Delay @ 255 2 x y @ delay x + y*256 microseconds
+
+ The code is currently dimensioned to support a chain with
+ roughly 600 entries and 20 loop counters.
...
- The following examples assume that waves with ids 0 to 12 exist.
+ #!/usr/bin/env python
- # 0 255 0 57 0 0 (repeat 0 57 times)
- pi.wave_chain([0, 255, 0, 57, 0, 0])
+ import time
+ import pigpio
- # 0 1 255 0 0 2 0 (repeat 0+1 512 times)
- pi.wave_chain([0, 1, 255, 0, 0, 2, 0])
+ WAVES=5
+ GPIO=4
- # 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
- pi.wave_chain([0, 1, 255, 1, 0, 0, 1])
+ wid=[0]*WAVES
- # 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
- pi.wave_chain([0, 1, 2, 3, 255, 2, 13, 0, 0])
+ pi = pigpio.pi() # Connect to local Pi.
+
+ pi.set_mode(GPIO, pigpio.OUTPUT);
+
+ for i in range(WAVES):
+ pi.wave_add_generic([
+ pigpio.pulse(1<
+.br
+#include
.br
.br
-// 0 255 0 57 0 0 (repeat 0 57 times)
+#define WAVES 5
.br
-status = wave_chain((char []){0, 255, 0, 57, 0, 0}, 6);
+#define GPIO 4
.br
.br
-// 0 1 255 0 0 2 0 (repeat 0+1 512 times)
+int main(int argc, char *argv[])
.br
-status = wave_chain((char []){0, 1, 255, 0, 0, 2, 0}, 7);
+{
+.br
+ int i, wid[WAVES];
.br
.br
-// 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
-.br
-status = wave_chain((char []){0, 1, 255, 1, 0, 0, 1}, 7);
+ if (pigpio_start(0, 0)<0) return -1;
.br
.br
-// 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
-.br
-status = wave_chain(
-.br
- (char []){0, 1, 2, 3, 255, 2, 13, 0, 0}, 9);
+ set_mode(GPIO, PI_OUTPUT);
.br
.br
-// The following repeats 5 65793 times, transmits 6,
+ for (i=0; i
*/
-/* PIGPIOD_IF_VERSION 16 */
+/* PIGPIOD_IF_VERSION 17 */
#include
#include
diff --git a/pigpiod_if.h b/pigpiod_if.h
index 5f32ffe..ae96930 100644
--- a/pigpiod_if.h
+++ b/pigpiod_if.h
@@ -30,7 +30,7 @@ For more information, please refer to
#include "pigpio.h"
-#define PIGPIOD_IF_VERSION 16
+#define PIGPIOD_IF_VERSION 17
/*TEXT
@@ -204,9 +204,6 @@ wave_get_cbs Length in cbs of the current waveform
wave_get_high_cbs Length of longest waveform so far
wave_get_max_cbs Absolute maximum allowed cbs
-wave_tx_start Creates/transmits a waveform (DEPRECATED)
-wave_tx_repeat Creates/transmits a waveform repeatedly (DEPRECATED)
-
I2C
i2c_open Opens an I2C device
@@ -914,8 +911,8 @@ int hardware_PWM(unsigned gpio, unsigned PWMfreq, uint32_t PWMduty);
Starts hardware PWM on a gpio at the specified frequency and dutycycle.
Frequencies above 30MHz are unlikely to work.
-NOTE: Any waveform started by [*wave_send_once*], [*wave_send_repeat*], [*wave_tx_start*], [*wave_tx_repeat*], or [*wave_chain*]
-will be cancelled.
+NOTE: Any waveform started by [*wave_send_once*], [*wave_send_repeat*],
+or [*wave_chain*] will be cancelled.
This function is only valid if the pigpio main clock is PCM. The
main clock defaults to PCM but may be overridden when the pigpio
@@ -1081,8 +1078,9 @@ D*/
int wave_create(void);
/*D
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.
+calls to the [*wave_add_**] functions. Upon success a wave id
+greater than or equal to 0 is returned, otherwise PI_EMPTY_WAVEFORM,
+PI_TOO_MANY_CBS, PI_TOO_MANY_OOL, or PI_NO_WAVEFORM_ID.
The data provided by the [*wave_add_**] functions is consumed by this
function.
@@ -1134,8 +1132,7 @@ D*/
/*F*/
int wave_delete(unsigned wave_id);
/*D
-This function deletes all created waveforms with ids greater than or
-equal to wave_id.
+This function deletes the waveform with id wave_id.
. .
wave_id: >=0, as returned by [*wave_create*].
@@ -1146,26 +1143,6 @@ Wave ids are allocated in order, 0, 1, 2, etc.
Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
D*/
-/*F*/
-int wave_tx_start(void);
-/*D
-This function is deprecated and should no longer be used.
-
-Use [*wave_create*]/[*wave_send_**] instead.
-
-NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled.
-D*/
-
-/*F*/
-int wave_tx_repeat(void);
-/*D
-This function is deprecated and should no longer be used.
-
-Use [*wave_create*]/[*wave_send_**] instead.
-
-NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled.
-D*/
-
/*F*/
int wave_send_once(unsigned wave_id);
/*D
@@ -1207,7 +1184,7 @@ This function transmits a chain of waveforms.
NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled.
The waves to be transmitted are specified by the contents of buf
-which contains an ordered list of wave_ids and optional command
+which contains an ordered list of [*wave_id*]s and optional command
codes and related data.
. .
@@ -1215,51 +1192,77 @@ codes and related data.
bufSize: the number of bytes in buf
. .
-Returns 0 if OK, otherwise PI_BAD_REPEAT_CNT, PI_BAD_REPEAT_WID,
-PI_BAD_CHAIN_CMD, PI_TOO_MANY_COUNTS, or PI_BAD_WAVE_ID.
+Returns 0 if OK, otherwise PI_CHAIN_NESTING, PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD, PI_CHAIN_COUNTER,
+PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG, or PI_BAD_WAVE_ID.
-Each wave is transmitted in the order specified. A wave may only
-occur once per chain. Waves may be transmitted multiple times by
-using the repeat command. The repeat command specifies a wave id
-and a count. The wave id must occur earlier in the chain. All the
-waves between wave id and the repeat command are transmitted count
-times.
+Each wave is transmitted in the order specified. A wave may
+occur multiple times per chain.
-Repeat commands may not be nested. The minimum repeat count is 2.
-A maximum of 5 repeat commands is supported per chain.
+A blocks of waves may be transmitted multiple times by using
+the loop commands. The block is bracketed by loop start and
+end commands. Loops may be nested.
+
+Delays between waves may be added with the delay command.
The following command codes are supported:
-Name @ Cmd & Data @ Meaning
-Repeat @ 255 wid C0 C1 C2 @ Repeat from wid count times
-count = C0 + C1*256 + C2*65536
+Name @ Cmd & Data @ Meaning
+Loop Start @ 255 0 @ Identify start of a wave block
+Loop Repeat @ 255 1 x y @ loop x + y*256 times
+Delay @ 255 2 x y @ delay x + y*256 microseconds
+
+The code is currently dimensioned to support a chain with roughly
+600 entries and 20 loop counters.
...
-The following examples assume that waves with ids 0 to 12 exist.
+#include
+#include
-// 0 255 0 57 0 0 (repeat 0 57 times)
-status = wave_chain((char []){0, 255, 0, 57, 0, 0}, 6);
+#define WAVES 5
+#define GPIO 4
-// 0 1 255 0 0 2 0 (repeat 0+1 512 times)
-status = wave_chain((char []){0, 1, 255, 0, 0, 2, 0}, 7);
+int main(int argc, char *argv[])
+{
+ int i, wid[WAVES];
-// 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
-status = wave_chain((char []){0, 1, 255, 1, 0, 0, 1}, 7);
+ if (pigpio_start(0, 0)<0) return -1;
-// 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
-status = wave_chain(
- (char []){0, 1, 2, 3, 255, 2, 13, 0, 0}, 9);
+ set_mode(GPIO, PI_OUTPUT);
-// The following repeats 5 65793 times, transmits 6,
-// repeats 7+8 514 times, transmits 12,
-// repeats 9+11+10 197121 times.
-// 5 255 5 1 1 1 6 7 8 255 7 2 2 0 12 9 11 10 255 9 1 2 3
-char chain[] = {
- 5, 255, 5, 1, 1, 1,
- 6, 7, 8, 255, 7, 2, 2, 0,
- 12, 9, 11, 10, 255, 9, 1, 2, 3};
+ for (i=0; i/dev/pigpio
read -t 1 s /dev/pigpio
+echo "wvcre" >/dev/pigpio
+read -t 1 w /dev/pigpio
read -t 1 s /dev/pigpio
read -t 1 s /dev/pigpio
+echo "wvcre" >/dev/pigpio
+read -t 1 w /dev/pigpio
read -t 1 s /dev/pigpio
read -t 1 s /dev/pigpio
read -t 1 s /dev/pigpio
+echo "wvtxr $w" >/dev/pigpio
read -t 1 s /dev/pigpio
read -t 1 s