diff --git a/.gitignore b/.gitignore
index 98748da3..4449b61f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
*.o
*.so
+*.so.*
*.pyc
pig2vcd
pigpiod
@@ -11,5 +12,10 @@ __pycache__
build
dist
*.egg-info
-wavepad_jitter.py
+# DOC files
+DOC/dbase/pigpio.sqlite.*
+DOC/tmp
+DOC/MAN/*
+!DOC/MAN/README*
+DOC/HTML/*.html
diff --git a/DOC/MAN/README b/DOC/MAN/README
index 2a89c86a..cde5d85e 100644
--- a/DOC/MAN/README
+++ b/DOC/MAN/README
@@ -1,2 +1 @@
-Placeholder directory for man pages.
-
+Placeholder directory for man pages.
diff --git a/DOC/dbase/pigpio.sqlite b/DOC/dbase/pigpio.sqlite
index 0820b48e..531ccfdf 100644
Binary files a/DOC/dbase/pigpio.sqlite and b/DOC/dbase/pigpio.sqlite differ
diff --git a/DOC/src/defs/pigs.def b/DOC/src/defs/pigs.def
index ff5e98d7..2f6d23c6 100644
--- a/DOC/src/defs/pigs.def
+++ b/DOC/src/defs/pigs.def
@@ -320,6 +320,7 @@ WVAG trips :: Add generic pulses to waveform :: gpioWaveAddGeneric
WVAS u b db sb o bvs :: Add serial data to waveform :: gpioWaveAddSerial
WVCRE :: Create a waveform :: gpioWaveCreate
+WVCAP :: Create a waveform of fixed size :: gpioWaveCreatePad
WVDEL wid :: Delete selected waveform :: gpioWaveDelete
WVTX wid :: Transmits waveform once :: gpioWaveTxSend
@@ -2783,6 +2784,49 @@ $ pigs wvcre
ERROR: attempt to create an empty waveform
...
+WVCAP ::
+
+Similar to [*WVCRE*], this command creates a waveform but pads the consumed
+resources to a fixed size, specified as a percent of total resource.
+Padded waves of equal size can be re-cycled efficiently allowing newly
+created waves to re-use the resources of deleted waves of the same dimension.
+
+Upon success a wave id (>=0) is returned. On error a negative status
+code will be returned.
+
+The data provided by the [*WVAG*] and [*WVAS*] commands are
+consumed by this command.
+
+As many waveforms may be created as there is space available.
+The wave id is passed to [*WVTX*] or [*WVTXR*] to specify the
+waveform to transmit.
+
+Normal usage would be
+
+Step 1. [*WVCLR*] to clear all waveforms and added data.
+
+Step 2. [*WVAG*]/[*WVAS*] calls to supply the waveform data.
+
+Step 3. [*WVCAP*] to create a waveform of a uniform size.
+
+Step 4. [*WVTX*] or [*WVTXR*] with the id of the waveform to transmit.
+
+Repeat steps 2 - 4 as needed.
+
+Step 5. Any wave id can now be deleted and another wave of the same size
+ can be created in its place.
+
+...
+# Create a wave that consumes 50% of the total resource:
+
+$ pigs wvag 16 0 5000000 0 16 5000000
+2
+$ pigs wvcap 50
+0
+$ pigs wvtx 0
+11918
+...
+
WVDEL ::
This command deletes the waveform with id [*wid*].
diff --git a/command.c b/command.c
index 4a1da4dc..ffc34630 100644
--- a/command.c
+++ b/command.c
@@ -201,7 +201,8 @@ cmdInfo_t cmdInfo[]=
{PI_CMD_WVBSY, "WVBSY", 101, 2, 1}, // gpioWaveTxBusy
{PI_CMD_WVCHA, "WVCHA", 197, 0, 0}, // gpioWaveChain
{PI_CMD_WVCLR, "WVCLR", 101, 0, 1}, // gpioWaveClear
- {PI_CMD_WVCRE, "WVCRE", 101, 2, 1}, // gpioWaveCreate
+ {PI_CMD_WVCRE, "WVCRE", 101, 2, 1}, // gpioWaveCreate
+ {PI_CMD_WVCAP, "WVCAP", 112, 2, 1}, // gpioWaveCreatePad
{PI_CMD_WVDEL, "WVDEL", 112, 0, 1}, // gpioWaveDelete
{PI_CMD_WVGO, "WVGO" , 101, 2, 0}, // gpioWaveTxStart
{PI_CMD_WVGOR, "WVGOR", 101, 2, 0}, // gpioWaveTxStart
@@ -693,7 +694,7 @@ int cmdParse(
case 112: /* BI2CC FC GDC GPW I2CC I2CRB
MG MICS MILS MODEG NC NP PADG PFG PRG
PROCD PROCP PROCS PRRG R READ SLRC SPIC
- WVDEL WVSC WVSM WVSP WVTX WVTXR BSPIC
+ WVCAP WVDEL WVSC WVSM WVSP WVTX WVTXR BSPIC
One positive parameter.
*/
diff --git a/pigpio.3 b/pigpio.3
index cd77e189..c878cbd2 100644
--- a/pigpio.3
+++ b/pigpio.3
@@ -584,6 +584,8 @@ gpioWaveAddSerial Adds serial data to the waveform
.br
gpioWaveCreate Creates a waveform from added data
.br
+gpioWaveCreatePad Creates a waveform of fixed size from added data
+.br
gpioWaveDelete Deletes a waveform
.br
@@ -2662,6 +2664,89 @@ 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.
+.IP "\fBint gpioWaveCreatePad(int pctCB, int pctBOOL, int pctTOOL)\fP"
+.IP "" 4
+Similar to \fBgpioWaveCreate\fP, this function creates a waveform but pads the consumed
+resources. Padded waves of equal dimension can be re-cycled efficiently allowing
+newly created waves to re-use the resources of deleted waves of the same dimension.
+
+.br
+
+.br
+
+.EX
+pctCB: 0-100, the percent of all DMA control blocks to consume.
+.br
+pctBOOL: 0-100, percent On-Off-Level (OOL) buffer to consume for wave output.
+.br
+pctTOOL: 0-100, the percent of OOL buffer to consume for wave input (flags).
+.br
+
+.EE
+
+.br
+
+.br
+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
+
+.br
+Waveform data provided by \fBgpioWaveAdd*\fP and \fBrawWaveAdd*\fP functions are
+consumed by this function.
+
+.br
+
+.br
+A usage would be the creation of two waves where one is filled while the other
+is being transmitted. Each wave is assigned 50% of the resources.
+This buffer structure allows the transmission of infinite wave sequences.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+ // get firstWaveChunk, somehow
+.br
+ gpioWaveAddGeneric(firstWaveChunk);
+.br
+ wid = gpioWaveCreatePad(50, 50, 0);
+.br
+ gpioWaveTxSend(wid, PI_WAVE_MODE_ONE_SHOT);
+.br
+ // get nextWaveChunk
+.br
+
+.br
+ while (nextWaveChunk) {
+.br
+ gpioWaveAddGeneric(nextWaveChunk);
+.br
+ nextWid = gpioWaveCreatePad(50, 50, 0);
+.br
+ gpioWaveTxSend(nextWid, PI_WAVE_MODE_ONE_SHOT_SYNC);
+.br
+ while(gpioWaveTxAt() == wid) time_sleep(0.1);
+.br
+ gpioWaveDelete(wid);
+.br
+ wid = nextWid;
+.br
+ // get nextWaveChunk
+.br
+ }
+.br
+
+.EE
+
+.br
+
+.br
+
.IP "\fBint gpioWaveDelete(unsigned wave_id)\fP"
.IP "" 4
This function deletes the waveform with id wave_id.
@@ -9484,6 +9569,27 @@ An array of script parameters.
.br
+.IP "\fBpctBOOL\fP: 0-100" 0
+percent On-Off-Level (OOL) buffer to consume for wave output.
+
+.br
+
+.br
+
+.IP "\fBpctCB\fP: 0-100" 0
+the percent of all DMA control blocks to consume.
+
+.br
+
+.br
+
+.IP "\fBpctTOOL\fP: 0-100" 0
+the percent of OOL buffer to consume for wave input (flags).
+
+.br
+
+.br
+
.IP "\fBpi_i2c_msg_t\fP" 0
.EX
@@ -10636,6 +10742,8 @@ A 16-bit word value.
.br
#define PI_CMD_PROCU 117
.br
+#define PI_CMD_WVCAP 118
+.br
.br
diff --git a/pigpio.c b/pigpio.c
index 7cd7cbfc..1bdae124 100644
--- a/pigpio.c
+++ b/pigpio.c
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to
*/
-/* pigpio version 75 */
+/* pigpio version 76 */
/* include ------------------------------------------------------- */
@@ -396,6 +396,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
#define DMA_DEST_WIDTH (1<< 5)
#define DMA_DEST_INC (1<< 4)
#define DMA_WAIT_RESP (1<< 3)
+#define DMA_TDMODE (1<< 1)
#define DMA_DEBUG_READ_ERR (1<<2)
#define DMA_DEBUG_FIFO_ERR (1<<1)
@@ -664,6 +665,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
/* --------------------------------------------------------------- */
#define NORMAL_DMA (DMA_NO_WIDE_BURSTS | DMA_WAIT_RESP)
+#define TWO_BEAT_DMA (DMA_TDMODE | DMA_BURST_LENGTH(1))
#define TIMED_DMA(x) (DMA_DEST_DREQ | DMA_PERIPHERAL_MAPPING(x))
@@ -2434,6 +2436,27 @@ static int myDoCommand(uintptr_t *p, unsigned bufSize, char *buf)
case PI_CMD_WVCRE: res = gpioWaveCreate(); break;
+ case PI_CMD_WVCAP:
+ /* Make WVCAP variadic */
+ if (p[3] == 4)
+ {
+ memcpy(&tmp3, buf, 4); /* percent TOOL */
+ res = gpioWaveCreatePad(p[1], p[2], tmp3); /* rawWaveAdd* usage */
+ break;
+ }
+ if (p[2] && p[3]==0)
+ {
+ res = gpioWaveCreatePad(p[1], p[2], 0);
+ break;
+ }
+ if (p[2]==0 && p[3]==0)
+ {
+ res = gpioWaveCreatePad(p[1], p[1], 0); /* typical usage */
+ break;
+ }
+ res = PI_BAD_WAVE_ID; // FIX?
+ break;
+
case PI_CMD_WVDEL: res = gpioWaveDelete(p[1]); break;
case PI_CMD_WVGO: res = gpioWaveTxStart(PI_WAVE_MODE_ONE_SHOT); break;
@@ -2977,8 +3000,7 @@ static void waveCBsOOLs(int *numCBs, int *numBOOLs, int *numTOOLs)
for (i=0; iinfo = TWO_BEAT_DMA;
+ p->src = waveOOLPOadr(botOOL);
+ waveSetOOL(botOOL++, waves[i].gpioOn);
+ s_stride = waveOOLPOadr(botOOL) - p->src;
+ waveSetOOL(botOOL++, waves[i].gpioOff);
+ p->dst = ((GPIO_BASE + (GPSET0*4)) & 0x00ffffff) | PI_PERI_BUS;
+ p->length = (2<<16) + 4; // 2 transfers of 4 bytes each
+ p->stride = (12<<16) + s_stride; // d_stride = (GPCLR0-GPSET0)*4 = 12
+ p->next = waveCbPOadr(botCB);
+ }
+ if (waves[i].gpioOn && !waves[i].gpioOff)
{
waveSetOOL(botOOL, waves[i].gpioOn);
@@ -3052,8 +3090,7 @@ static int wave2Cbs(unsigned wave_mode, int *CB, int *BOOL, int *TOOL)
p->length = 4;
p->next = waveCbPOadr(botCB);
}
-
- if (waves[i].gpioOff)
+ if (waves[i].gpioOff && !waves[i].gpioOn)
{
waveSetOOL(botOOL, waves[i].gpioOff);
@@ -3065,7 +3102,6 @@ static int wave2Cbs(unsigned wave_mode, int *CB, int *BOOL, int *TOOL)
p->length = 4;
p->next = waveCbPOadr(botCB);
}
-
if (waves[i].flags & WAVE_FLAG_READ)
{
p = rawWaveCBAdr(botCB++);
@@ -3130,6 +3166,28 @@ static int wave2Cbs(unsigned wave_mode, int *CB, int *BOOL, int *TOOL)
}
}
+ if (numCB)
+ {
+ /* Pad the wave */
+
+ botCB = *CB + numCB - 1;
+ botOOL = *BOOL + numBOOL - 1;
+ topOOL = *TOOL - numTOOL;
+
+ /* Link the last CB to end of wave */
+
+ p->next = waveCbPOadr(botCB);
+
+ /* Insert sentinel CB at end of DMA */
+
+ p = rawWaveCBAdr(botCB++);
+ p->info = NORMAL_DMA | DMA_DEST_IGNORE;
+ p->src = waveOOLPOadr(botOOL++);
+ p->dst = ((GPIO_BASE + (GPSET0*4)) & 0x00ffffff) | PI_PERI_BUS;
+ p->length = 4;
+ p->next = 0;
+ }
+
if (p != NULL)
{
if (wave_mode == PI_WAVE_MODE_ONE_SHOT)
@@ -3324,9 +3382,7 @@ int rawWaveAddGeneric(unsigned numIn1, rawWave_t *in1)
cbs += waveDelayCBs(tDelay);
- if (out[outPos].gpioOn) cbs++; /* one cb if gpio on */
-
- if (out[outPos].gpioOff) cbs++; /* one cb if gpio off */
+ if (out[outPos].gpioOn || out[outPos].gpioOff) cbs++;
if (out[outPos].flags & WAVE_FLAG_READ)
{
@@ -9566,7 +9622,7 @@ int gpioWaveCreate(void)
/* What resources are needed? */
- waveCBsOOLs(&numCB, &numBOOL, &numTOOL);
+ waveCBsOOLs(&numCB, &numBOOL, &numTOOL);
wid = -1;
@@ -9589,10 +9645,10 @@ int gpioWaveCreate(void)
{
/* Are there enough spare resources? */
- if ((numCB+waveOutBotCB) >= NUM_WAVE_CBS)
+ if ((numCB+waveOutBotCB) > NUM_WAVE_CBS)
return PI_TOO_MANY_CBS;
- if ((numBOOL+waveOutBotOOL) >= (waveOutTopOOL-numTOOL))
+ if ((numBOOL+waveOutBotOOL) > (waveOutTopOOL-numTOOL))
return PI_TOO_MANY_OOL;
if (wid >= PI_MAX_WAVES)
@@ -9619,7 +9675,7 @@ int gpioWaveCreate(void)
BOOL = waveInfo[wid].botOOL;
TOOL = waveInfo[wid].topOOL;
- wave2Cbs(PI_WAVE_MODE_ONE_SHOT, &CB, &BOOL, &TOOL);
+ wave2Cbs(PI_WAVE_MODE_ONE_SHOT, &CB, &BOOL, &TOOL, 0, 0, 0);
/* Sanity check. */
@@ -9633,6 +9689,9 @@ int gpioWaveCreate(void)
numTOOL, waveInfo[wid].topOOL-TOOL);
}
+ DBG(DBG_USER, "Wave Stats: wid=%d CBs %d BOOL %d TOOL %d", wid,
+ numCB, numBOOL, numTOOL);
+
waveInfo[wid].deleted = 0;
/* Consume waves. */
@@ -9646,6 +9705,124 @@ int gpioWaveCreate(void)
return wid;
}
+int gpioWaveCreatePad(int pctCB, int pctBOOL, int pctTOOL)
+{
+ int i, wid;
+ int numCB, numBOOL, numTOOL;
+ int CB, BOOL, TOOL;
+
+ DBG(DBG_USER, "%d, %d, %d", pctCB, pctBOOL, pctTOOL);
+
+ CHECK_INITED;
+
+ if (pctCB < 0 || pctCB > 100)
+ SOFT_ERROR(PI_BAD_PARAM, "bad wave param, pctCB=(%d)", pctCB);
+ if (pctBOOL < 0 || pctBOOL > 100)
+ SOFT_ERROR(PI_BAD_PARAM, "bad wave param, pctBOOL=(%d)", pctBOOL);
+ if (pctTOOL < 0 || pctTOOL > 100)
+ SOFT_ERROR(PI_BAD_PARAM, "bad wave param, pctTOOL=(%d)", pctTOOL);
+
+ if (wfc[wfcur] == 0) return PI_EMPTY_WAVEFORM;
+
+ /* What resources are needed? */
+ waveCBsOOLs(&numCB, &numBOOL, &numTOOL);
+
+ /* Amount of pad required */
+ CB = (NUM_WAVE_CBS - PI_WAVE_COUNT_PAGES*CBS_PER_OPAGE) * pctCB / 100;
+ BOOL = (NUM_WAVE_OOL - PI_WAVE_COUNT_PAGES*OOL_PER_OPAGE) * pctBOOL /100;
+ TOOL = (NUM_WAVE_OOL - PI_WAVE_COUNT_PAGES*OOL_PER_OPAGE) * pctTOOL /100;
+
+ /* Reject if wave is too big */
+ if (numCB > CB) return PI_TOO_MANY_CBS;
+ if (numBOOL > BOOL) return PI_TOO_MANY_OOL;
+ if (numTOOL > TOOL) return PI_TOO_MANY_OOL;
+
+ /* Set the padding */
+ numCB = CB;
+ numBOOL = BOOL;
+ numTOOL = TOOL;
+
+
+ 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, numCB, numBOOL, numTOOL);
+
+ /* Sanity check. */
+
+ if ( (numCB != (CB-waveInfo[wid].botCB)) ||
+ (numBOOL != (BOOL-waveInfo[wid].botOOL)) ||
+ (numTOOL != (waveInfo[wid].topOOL-TOOL)) )
+ {
+ DBG(DBG_ALWAYS, "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);
+ }
+
+ DBG(DBG_USER, "Wave padding: wid=%d CBs %d BOOL %d TOOL %d", wid,
+ numCB, numBOOL, numTOOL);
+
+ waveInfo[wid].deleted = 0;
+
+ /* Consume waves. */
+
+ wfc[0] = 0;
+ wfc[1] = 0;
+ wfc[2] = 0;
+
+ wfcur = 0;
+
+ return wid;
+}
/* ----------------------------------------------------------------------- */
int gpioWaveDelete(unsigned wave_id)
diff --git a/pigpio.h b/pigpio.h
index 7701b453..059d7515 100644
--- a/pigpio.h
+++ b/pigpio.h
@@ -30,7 +30,7 @@ For more information, please refer to
#include
#include
-#define PIGPIO_VERSION 75
+#define PIGPIO_VERSION 76
/*TEXT
@@ -322,6 +322,7 @@ gpioWaveAddGeneric Adds a series of pulses to the waveform
gpioWaveAddSerial Adds serial data to the waveform
gpioWaveCreate Creates a waveform from added data
+gpioWaveCreatePad Creates a waveform of fixed size from added data
gpioWaveDelete Deletes a waveform
gpioWaveTxSend Transmits a waveform
@@ -1987,6 +1988,49 @@ PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
D*/
+/*F*/
+int gpioWaveCreatePad(int pctCB, int pctBOOL, int pctTOOL);
+/*D
+Similar to [*gpioWaveCreate*], this function creates a waveform but pads the consumed
+resources. Padded waves of equal dimension can be re-cycled efficiently allowing
+newly created waves to re-use the resources of deleted waves of the same dimension.
+
+. .
+pctCB: 0-100, the percent of all DMA control blocks to consume.
+pctBOOL: 0-100, percent On-Off-Level (OOL) buffer to consume for wave output.
+pctTOOL: 0-100, the percent of OOL buffer to consume for wave input (flags).
+. .
+
+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.
+
+Waveform data provided by [*gpioWaveAdd**] and [*rawWaveAdd**] functions are
+consumed by this function.
+
+A usage would be the creation of two waves where one is filled while the other
+is being transmitted. Each wave is assigned 50% of the resources.
+This buffer structure allows the transmission of infinite wave sequences.
+
+...
+ // get firstWaveChunk, somehow
+ gpioWaveAddGeneric(firstWaveChunk);
+ wid = gpioWaveCreatePad(50, 50, 0);
+ gpioWaveTxSend(wid, PI_WAVE_MODE_ONE_SHOT);
+ // get nextWaveChunk
+
+ while (nextWaveChunk) {
+ gpioWaveAddGeneric(nextWaveChunk);
+ nextWid = gpioWaveCreatePad(50, 50, 0);
+ gpioWaveTxSend(nextWid, PI_WAVE_MODE_ONE_SHOT_SYNC);
+ while(gpioWaveTxAt() == wid) time_sleep(0.1);
+ gpioWaveDelete(wid);
+ wid = nextWid;
+ // get nextWaveChunk
+ }
+...
+
+D*/
+
/*F*/
int gpioWaveDelete(unsigned wave_id);
/*D
@@ -5760,6 +5804,15 @@ high and low levels.
*param::
An array of script parameters.
+pctBOOL:: 0-100
+percent On-Off-Level (OOL) buffer to consume for wave output.
+
+pctCB:: 0-100
+the percent of all DMA control blocks to consume.
+
+pctTOOL:: 0-100
+the percent of OOL buffer to consume for wave input (flags).
+
pi_i2c_msg_t::
. .
typedef struct
@@ -6271,6 +6324,7 @@ PARAMS*/
#define PI_CMD_EVT 116
#define PI_CMD_PROCU 117
+#define PI_CMD_WVCAP 118
/*DEF_E*/
diff --git a/pigpio.py b/pigpio.py
index cfaf845e..978aff2f 100644
--- a/pigpio.py
+++ b/pigpio.py
@@ -288,6 +288,7 @@
wave_add_serial Adds serial data to the waveform
wave_create Creates a waveform from added data
+wave_create_and_pad Creates a waveform of fixed size from added data
wave_delete Deletes a waveform
wave_send_once Transmits a waveform once
@@ -571,6 +572,7 @@
_PI_CMD_EVT =116
_PI_CMD_PROCU=117
+_PI_CMD_WVCAP=118
# pigpio error numbers
@@ -2304,6 +2306,51 @@ def wave_create(self):
"""
return _u2i(_pigpio_command(self.sl, _PI_CMD_WVCRE, 0, 0))
+ def wave_create_and_pad(self, percent):
+ """
+ This function creates a waveform like [*wave_create*] but pads the consumed
+ resources. Where percent gives the percentage of the resources to use
+ (in terms of the theoretical maximum, not the current amount free).
+ This allows the reuse of deleted waves while a transmission is active.
+
+ 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.
+
+ . .
+ percent: 0-100, size of waveform as percentage of maximum available.
+ . .
+
+ The data provided by the [*wave_add_**] functions are 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.
+
+ A usage would be the creation of two waves where one is filled while the
+ other is being transmitted. Each wave is assigned 50% of the resources.
+ This buffer structure allows the transmission of infinite wave sequences.
+
+ Normal usage:
+
+ 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_and_pad*] to create a waveform of uniform size.
+
+ Step 4. [*wave_send_**] with the id of the waveform to transmit.
+
+ Repeat steps 2-4 as needed.
+
+ Step 5. Any wave id can now be deleted and another wave of the same size
+ can be created in its place.
+
+ ...
+ wid = pi.wave_create_and_pad(50)
+ ...
+ """
+ return _u2i(_pigpio_command(self.sl, _PI_CMD_WVCAP, percent, 0))
+
def wave_delete(self, wave_id):
"""
This function deletes the waveform with id wave_id.
@@ -5582,6 +5629,9 @@ def xref():
When scripts are started they can receive up to 10 parameters
to define their operation.
+ percent:: 0-100
+ The size of waveform as percentage of maximum available.
+
port:
The port used by the pigpio daemon, defaults to 8888.
diff --git a/pigpiod_if2.3 b/pigpiod_if2.3
index 33c55e97..f07de8df 100644
--- a/pigpiod_if2.3
+++ b/pigpiod_if2.3
@@ -546,6 +546,8 @@ wave_add_serial Adds serial data to the waveform
.br
wave_create Creates a waveform from added data
.br
+wave_create_and_pad Creates a waveform of fixed size from added data
+.br
wave_delete Deletes one or more waveforms
.br
@@ -2391,6 +2393,87 @@ 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.
+.IP "\fBint wave_create_and_pad(int pi, int percent)\fP"
+.IP "" 4
+This function creates a waveform like \fBwave_create\fP but pads the consumed
+resources. Where percent gives the percentage of the resources to use (in terms
+of the theoretical maximum, not the current amount free). This allows the reuse
+.br
+of deleted waves while a transmission is active.
+
+.br
+
+.br
+
+.EX
+pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+percent: 0-100, size of waveform as percentage of maximum available.
+.br
+
+.EE
+
+.br
+
+.br
+The data provided by the \fBwave_add_*\fP functions are consumed by this
+function.
+
+.br
+
+.br
+As many waveforms may be created as there is space available. The
+wave id is passed to \fBwave_send_*\fP to specify the waveform to transmit.
+
+.br
+
+.br
+A usage would be the creation of two waves where one is filled while the other
+is being transmitted. Each wave is assigned 50% of the resources.
+This buffer structure allows the transmission of infinite wave sequences.
+
+.br
+
+.br
+Normal usage:
+
+.br
+
+.br
+Step 1. \fBwave_clear\fP to clear all waveforms and added data.
+
+.br
+
+.br
+Step 2. \fBwave_add_*\fP calls to supply the waveform data.
+
+.br
+
+.br
+Step 3. \fBwave_create_and_pad\fP to create a waveform of uniform size.
+
+.br
+
+.br
+Step 4. \fBwave_send_*\fP with the id of the waveform to transmit.
+
+.br
+
+.br
+Repeat steps 2-4 as needed.
+
+.br
+
+.br
+Step 5. Any wave id can now be deleted and another wave of the same size
+ can be created in its place.
+
+.br
+
+.br
+Returns the new waveform id if OK, otherwise PI_EMPTY_WAVEFORM,
+PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
+
.IP "\fBint wave_delete(int pi, unsigned wave_id)\fP"
.IP "" 4
This function deletes the waveform with id wave_id.
@@ -7416,6 +7499,13 @@ An array of script parameters.
.br
+.IP "\fBpercent\fP: 0-100" 0
+The size of waveform as percentage of maximum available.
+
+.br
+
+.br
+
.IP "\fBpi\fP" 0
An integer defining a connected Pi. The value is returned by
\fBpigpio_start\fP upon success.
diff --git a/pigpiod_if2.c b/pigpiod_if2.c
index 90fb5fb5..7af8313c 100644
--- a/pigpiod_if2.c
+++ b/pigpiod_if2.c
@@ -953,6 +953,9 @@ int wave_add_serial(
int wave_create(int pi)
{return pigpio_command(pi, PI_CMD_WVCRE, 0, 0, 1);}
+int wave_create_and_pad(int pi, int percent)
+ {return pigpio_command(pi, PI_CMD_WVCAP, percent, 0, 1);}
+
int wave_delete(int pi, unsigned wave_id)
{return pigpio_command(pi, PI_CMD_WVDEL, wave_id, 0, 1);}
diff --git a/pigpiod_if2.h b/pigpiod_if2.h
index 8d6f1322..79d0223a 100644
--- a/pigpiod_if2.h
+++ b/pigpiod_if2.h
@@ -302,6 +302,7 @@ wave_add_generic Adds a series of pulses to the waveform
wave_add_serial Adds serial data to the waveform
wave_create Creates a waveform from added data
+wave_create_and_pad Creates a waveform of fixed size from added data
wave_delete Deletes one or more waveforms
wave_send_once Transmits a waveform once
@@ -1372,6 +1373,49 @@ PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
D*/
+/*F*/
+int wave_create_and_pad(int pi, int percent);
+/*D
+This function creates a waveform like [*wave_create*] but pads the consumed
+resources. Where percent gives the percentage of the resources to use (in terms
+of the theoretical maximum, not the current amount free). This allows the reuse
+of deleted waves while a transmission is active.
+
+. .
+pi: >=0 (as returned by [*pigpio_start*]).
+percent: 0-100, size of waveform as percentage of maximum available.
+. .
+
+The data provided by the [*wave_add_**] functions are 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.
+
+A usage would be the creation of two waves where one is filled while the other
+is being transmitted. Each wave is assigned 50% of the resources.
+This buffer structure allows the transmission of infinite wave sequences.
+
+Normal usage:
+
+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_and_pad*] to create a waveform of uniform size.
+
+Step 4. [*wave_send_**] with the id of the waveform to transmit.
+
+Repeat steps 2-4 as needed.
+
+Step 5. Any wave id can now be deleted and another wave of the same size
+ can be created in its place.
+
+Returns the new waveform id if OK, otherwise PI_EMPTY_WAVEFORM,
+PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
+D*/
+
+
/*F*/
int wave_delete(int pi, unsigned wave_id);
/*D
@@ -4083,6 +4127,9 @@ high and low levels.
*param::
An array of script parameters.
+percent:: 0-100
+The size of waveform as percentage of maximum available.
+
pi::
An integer defining a connected Pi. The value is returned by
[*pigpio_start*] upon success.
diff --git a/pigs.1 b/pigs.1
index ca31392f..9b6192c2 100644
--- a/pigs.1
+++ b/pigs.1
@@ -548,6 +548,9 @@ Add serial data to waveform
.B WVCRE
Create a waveform
.P
+.B WVCAP
+Create a waveform of fixed size
+.P
.B WVDEL wid
Delete selected waveform
.P
@@ -5139,6 +5142,77 @@ ERROR: attempt to create an empty waveform
.br
+.IP "\fBWVCAP \fP - Create a waveform of fixed size"
+.IP "" 4
+
+.br
+Similar to \fBWVCRE\fP, this command creates a waveform but pads the consumed
+resources to a fixed size, specified as a percent of total resource.
+Padded waves of equal size can be re-cycled efficiently allowing newly
+created waves to re-use the resources of deleted waves of the same dimension.
+
+.br
+Upon success a wave id (>=0) is returned. On error a negative status
+code will be returned.
+
+.br
+The data provided by the \fBWVAG\fP and \fBWVAS\fP commands are
+consumed by this command.
+
+.br
+As many waveforms may be created as there is space available.
+The wave id is passed to \fBWVTX\fP or \fBWVTXR\fP to specify the
+waveform to transmit.
+
+.br
+Normal usage would be
+
+.br
+Step 1. \fBWVCLR\fP to clear all waveforms and added data.
+
+.br
+Step 2. \fBWVAG\fP/\fBWVAS\fP calls to supply the waveform data.
+
+.br
+Step 3. \fBWVCAP\fP to create a waveform of a uniform size.
+
+.br
+Step 4. \fBWVTX\fP or \fBWVTXR\fP with the id of the waveform to transmit.
+
+.br
+Repeat steps 2 - 4 as needed.
+
+.br
+Step 5. Any wave id can now be deleted and another wave of the same size
+ can be created in its place.
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+# Create a wave that consumes 50% of the total resource:
+.br
+
+.br
+$ pigs wvag 16 0 5000000 0 16 5000000
+.br
+2
+.br
+$ pigs wvcap 50
+.br
+0
+.br
+$ pigs wvtx 0
+.br
+11918
+.br
+
+.EE
+
+.br
+
.IP "\fBWVDEL wid\fP - Delete selected waveform"
.IP "" 4
diff --git a/x_pigpio.c b/x_pigpio.c
index cd15389c..8119d73c 100644
--- a/x_pigpio.c
+++ b/x_pigpio.c
@@ -459,6 +459,51 @@ To the lascivious pleasing of a lute.\n\
c = gpioWaveGetMaxCbs();
CHECK(5, 21, c, 25016, 0, "wave get max cbs");
+
+ /* waveCreatePad tests */
+ gpioWaveTxStop();
+ gpioWaveClear();
+ gpioSetAlertFunc(GPIO, t5cbf);
+
+ e = gpioWaveAddGeneric(2, (gpioPulse_t[])
+ { {1<