Merge pull request #345 from joan2937/release-v76

Release v76
This commit is contained in:
Guy McSwain 2020-04-30 13:36:11 -05:00 committed by GitHub
commit 30e6b35574
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 825 additions and 22 deletions

8
.gitignore vendored
View File

@ -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

View File

@ -1,2 +1 @@
Placeholder directory for man pages.
Placeholder directory for man pages.

Binary file not shown.

View File

@ -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*].

View File

@ -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.
*/

108
pigpio.3
View File

@ -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

209
pigpio.c
View File

@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/
/* 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; i<numWaves; i++)
{
if (waves[i].gpioOn) {numCB++; numBOOL++;}
if (waves[i].gpioOff) {numCB++; numBOOL++;}
if (waves[i].gpioOn || waves[i].gpioOff) {numCB++; numBOOL++;}
if (waves[i].flags & WAVE_FLAG_READ) {numCB++; numTOOL++;}
if (waves[i].flags & WAVE_FLAG_TICK) {numCB++; numTOOL++;}
@ -2992,11 +3014,12 @@ static void waveCBsOOLs(int *numCBs, int *numBOOLs, int *numTOOLs)
/* ----------------------------------------------------------------------- */
static int wave2Cbs(unsigned wave_mode, int *CB, int *BOOL, int *TOOL)
static int wave2Cbs(unsigned wave_mode, int *CB, int *BOOL, int *TOOL,
int numCB, int numBOOL, int numTOOL)
{
int botCB=*CB, botOOL=*BOOL, topOOL=*TOOL;
int status;
int status, s_stride;
rawCbs_t *p=NULL;
@ -3040,7 +3063,22 @@ static int wave2Cbs(unsigned wave_mode, int *CB, int *BOOL, int *TOOL)
for (i=0; i<numWaves; i++)
{
if (waves[i].gpioOn)
if (waves[i].gpioOn && waves[i].gpioOff)
/* Use 2-beat burst */
{
p = rawWaveCBAdr(botCB++);
p->info = 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<waveOutCount; i++)
{
if (waveInfo[i].deleted &&
(waveInfo[i].numCB == numCB) &&
(waveInfo[i].numBOOL == numBOOL) &&
(waveInfo[i].numTOOL == numTOOL))
{
/* Reuse the deleted waves resources. */
wid = i;
break;
}
}
if (wid == -1)
{
/* Are there enough spare resources? */
if ((numCB+waveOutBotCB) > 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)

View File

@ -30,7 +30,7 @@ For more information, please refer to <http://unlicense.org/>
#include <stdint.h>
#include <pthread.h>
#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*/

View File

@ -288,6 +288,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 a waveform
wave_send_once Transmits a waveform once
@ -571,6 +572,7 @@ _PI_CMD_EVM =115
_PI_CMD_EVT =116
_PI_CMD_PROCU=117
_PI_CMD_WVCAP=118
# pigpio error numbers
@ -2304,6 +2306,51 @@ class pi():
"""
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.

View File

@ -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.

View File

@ -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);}

View File

@ -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.

74
pigs.1
View File

@ -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

View File

@ -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<<GPIO, 0, 10000},
{0, 1<<GPIO, 30000}
});
wid = gpioWaveCreatePad(50, 50, 0);
CHECK(5, 22, wid, 0, 0, "wave create pad, count==1, wid==");
e = gpioWaveAddGeneric(4, (gpioPulse_t[])
{ {1<<GPIO, 0, 10000},
{0, 1<<GPIO, 30000},
{1<<GPIO, 0, 60000},
{0, 1<<GPIO, 100000}
});
wid = gpioWaveCreatePad(50, 50, 0);
CHECK(5, 23, wid, 1, 0, "wave create pad, count==2, wid==");
c = gpioWaveDelete(0);
CHECK(5, 24, c, 0, 0, "delete wid==0 success");
e = gpioWaveAddGeneric(6, (gpioPulse_t[])
{ {1<<GPIO, 0, 10000},
{0, 1<<GPIO, 30000},
{1<<GPIO, 0, 60000},
{0, 1<<GPIO, 100000},
{1<<GPIO, 0, 60000},
{0, 1<<GPIO, 100000}
});
c = gpioWaveCreate();
CHECK(5, 25, c, -67, 0, "No more CBs using wave create");
wid = gpioWaveCreatePad(50, 50, 0);
CHECK(5, 26, wid, 0, 0, "wave create pad, count==3, wid==");
t5_count = 0;
e = gpioWaveChain((char[]) {1,0}, 2);
CHECK(5, 27, e, 0, 0, "wave chain [1,0]");
while (gpioWaveTxBusy()) time_sleep(0.1);
CHECK(5, 28, t5_count, 5, 1, "callback count==");
gpioSetAlertFunc(GPIO, NULL);
}
int t6_count;

View File

@ -483,6 +483,47 @@ To the lascivious pleasing of a lute.
e = pi.wave_delete(0)
CHECK(5, 33, e, 0, 0, "wave delete")
# wave_create_and_pad tests
t5cb = pi.callback(GPIO, pigpio.FALLING_EDGE, t5cbf)
pi.wave_clear()
pi.wave_add_generic([pigpio.pulse(1<<GPIO, 0, 10000),
pigpio.pulse(0, 1<<GPIO, 30000)])
wid = pi.wave_create_and_pad(50)
CHECK(5, 34, wid, 0, 0, "wave create and pad, wid==")
pi.wave_add_generic([pigpio.pulse(1<<GPIO, 0, 10000),
pigpio.pulse(0, 1<<GPIO, 30000),
pigpio.pulse(1<<GPIO, 0, 60000),
pigpio.pulse(0, 1<<GPIO, 100000)])
wid = pi.wave_create_and_pad(50)
CHECK(5, 35, wid, 1, 0, "wave create and pad, wid==")
c = pi.wave_delete(0);
CHECK(5, 36, c, 0, 0, "delete wid==0 success");
pi.wave_add_generic([pigpio.pulse(1<<GPIO, 0, 10000),
pigpio.pulse(0, 1<<GPIO, 30000),
pigpio.pulse(1<<GPIO, 0, 60000),
pigpio.pulse(0, 1<<GPIO, 100000),
pigpio.pulse(1<<GPIO, 0, 60000),
pigpio.pulse(0, 1<<GPIO, 100000)])
pigpio.exceptions = False
c = pi.wave_create()
CHECK(5, 37, c, -67, 0, "No more CBs using wave create")
pigpio.exceptions = True
wid = pi.wave_create_and_pad(50)
CHECK(5, 38, wid, 0, 0, "wave create pad, count==3, wid==")
t5_count = 0;
e = pi.wave_chain([1,0])
CHECK(5, 39, e, 0, 0, "wave chain [1,0]")
while pi.wave_tx_busy():
time.sleep(0.2)
CHECK(5, 40, t5_count, 10, 1, "callback count==")
t5cb.cancel()
t6_count=0

View File

@ -434,6 +434,50 @@ To the lascivious pleasing of a lute.\n\
CHECK(5, 21, c, 25016, 0, "wave get max cbs");
callback_cancel(id);
/* wave create and pad tests */
id = callback(pi, GPIO, FALLING_EDGE, t5cbf);
e = wave_clear(pi);
e = wave_add_generic(pi, 2, (gpioPulse_t[])
{ {1<<GPIO, 0, 10000},
{0, 1<<GPIO, 30000}
});
wid = wave_create_and_pad(pi, 50);
CHECK(5, 22, wid, 0, 0, "wave create pad, count==1, wid==");
e = wave_add_generic(pi, 4, (gpioPulse_t[])
{ {1<<GPIO, 0, 10000},
{0, 1<<GPIO, 30000},
{1<<GPIO, 0, 60000},
{0, 1<<GPIO, 100000}
});
wid = wave_create_and_pad(pi, 50);
CHECK(5, 23, wid, 1, 0, "wave create pad, count==2, wid==");
c = wave_delete(pi, 0);
CHECK(5, 24, c, 0, 0, "delete wid==0 success");
e = wave_add_generic(pi, 6, (gpioPulse_t[])
{ {1<<GPIO, 0, 10000},
{0, 1<<GPIO, 30000},
{1<<GPIO, 0, 60000},
{0, 1<<GPIO, 100000},
{1<<GPIO, 0, 60000},
{0, 1<<GPIO, 100000}
});
c = wave_create(pi);
CHECK(5, 25, c, -67, 0, "No more CBs using wave create");
wid = wave_create_and_pad(pi, 50);
CHECK(5, 26, wid, 0, 0, "wave create pad, count==3, wid==");
t5_count = 0;
e = wave_chain(pi, (char[]) {1,0}, 2);
CHECK(5, 27, e, 0, 0, "wave chain [1,0]");
while (wave_tx_busy(pi)) time_sleep(0.1);
CHECK(5, 28, t5_count, 5, 1, "callback count==");
callback_cancel(id);
}
int t6_count=0;

20
x_pigs
View File

@ -308,3 +308,23 @@ if [[ $s -ge 310 ]]; then echo "WVSP-b ok"; else echo "WVSP-b fail ($s)"; fi
s=$(pigs wvsp 2)
if [[ $s = 12000 ]]; then echo "WVSP-c ok"; else echo "WVSP-c fail ($s)"; fi
s=$(pigs wvclr )
s=$(pigs wvag 16 0 5000000 0 16 5000000)
wid=$(pigs wvcap 50)
if [[ $wid = 0 ]]; then echo "WVCAP-a ok"; else echo "WVCAP-a fail ($wid)"; fi
s=$(pigs wvag 16 0 5000000 0 16 5000000 16 0 5000000 0 16 5000000)
wid=$(pigs wvcap 50)
if [[ $wid = 1 ]]; then echo "WVCAP-b ok"; else echo "WVCAP-b fail ($wid)"; fi
s=$(pigs wvdel 0)
if [[ $s == "" ]]; then echo "WVCAP-c ok"; else echo "WVCAP-c fail ($s)"; fi
s=$(pigs wvag 16 0 5000000 0 16 5000000 16 0 5000000 0 16 5000000 16 0 5000000 0 16 5000000)
# Show WVCRE fails
wid=$(pigs wvcre)
if [[ $wid = -67 ]]; then echo "WVCAP-d ok"; else echo "WVCAP-d fail ($wid)"; fi
# but that WVCAP ok
wid=$(pigs wvcap 50)
if [[ $wid = 0 ]]; then echo "WVCAP-e ok"; else echo "WVCAP-e fail ($wid)"; fi