mirror of https://github.com/joan2937/pigpio
Merge branch 'wavesize' into develop
This commit is contained in:
commit
d0bd490204
|
@ -1,5 +1,6 @@
|
||||||
*.o
|
*.o
|
||||||
*.so
|
*.so
|
||||||
|
*.so.*
|
||||||
*.pyc
|
*.pyc
|
||||||
pig2vcd
|
pig2vcd
|
||||||
pigpiod
|
pigpiod
|
||||||
|
|
|
@ -201,7 +201,8 @@ cmdInfo_t cmdInfo[]=
|
||||||
{PI_CMD_WVBSY, "WVBSY", 101, 2, 1}, // gpioWaveTxBusy
|
{PI_CMD_WVBSY, "WVBSY", 101, 2, 1}, // gpioWaveTxBusy
|
||||||
{PI_CMD_WVCHA, "WVCHA", 197, 0, 0}, // gpioWaveChain
|
{PI_CMD_WVCHA, "WVCHA", 197, 0, 0}, // gpioWaveChain
|
||||||
{PI_CMD_WVCLR, "WVCLR", 101, 0, 1}, // gpioWaveClear
|
{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_WVDEL, "WVDEL", 112, 0, 1}, // gpioWaveDelete
|
||||||
{PI_CMD_WVGO, "WVGO" , 101, 2, 0}, // gpioWaveTxStart
|
{PI_CMD_WVGO, "WVGO" , 101, 2, 0}, // gpioWaveTxStart
|
||||||
{PI_CMD_WVGOR, "WVGOR", 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
|
case 112: /* BI2CC FC GDC GPW I2CC I2CRB
|
||||||
MG MICS MILS MODEG NC NP PADG PFG PRG
|
MG MICS MILS MODEG NC NP PADG PFG PRG
|
||||||
PROCD PROCP PROCS PRRG R READ SLRC SPIC
|
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.
|
One positive parameter.
|
||||||
*/
|
*/
|
||||||
|
|
207
pigpio.c
207
pigpio.c
|
@ -396,6 +396,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
|
||||||
#define DMA_DEST_WIDTH (1<< 5)
|
#define DMA_DEST_WIDTH (1<< 5)
|
||||||
#define DMA_DEST_INC (1<< 4)
|
#define DMA_DEST_INC (1<< 4)
|
||||||
#define DMA_WAIT_RESP (1<< 3)
|
#define DMA_WAIT_RESP (1<< 3)
|
||||||
|
#define DMA_TDMODE (1<< 1)
|
||||||
|
|
||||||
#define DMA_DEBUG_READ_ERR (1<<2)
|
#define DMA_DEBUG_READ_ERR (1<<2)
|
||||||
#define DMA_DEBUG_FIFO_ERR (1<<1)
|
#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 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))
|
#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_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_WVDEL: res = gpioWaveDelete(p[1]); break;
|
||||||
|
|
||||||
case PI_CMD_WVGO: res = gpioWaveTxStart(PI_WAVE_MODE_ONE_SHOT); 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++)
|
for (i=0; i<numWaves; i++)
|
||||||
{
|
{
|
||||||
if (waves[i].gpioOn) {numCB++; numBOOL++;}
|
if (waves[i].gpioOn || waves[i].gpioOff) {numCB++; numBOOL++;}
|
||||||
if (waves[i].gpioOff) {numCB++; numBOOL++;}
|
|
||||||
if (waves[i].flags & WAVE_FLAG_READ) {numCB++; numTOOL++;}
|
if (waves[i].flags & WAVE_FLAG_READ) {numCB++; numTOOL++;}
|
||||||
if (waves[i].flags & WAVE_FLAG_TICK) {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 botCB=*CB, botOOL=*BOOL, topOOL=*TOOL;
|
||||||
|
|
||||||
int status;
|
int status, s_stride;
|
||||||
|
|
||||||
rawCbs_t *p=NULL;
|
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++)
|
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);
|
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->length = 4;
|
||||||
p->next = waveCbPOadr(botCB);
|
p->next = waveCbPOadr(botCB);
|
||||||
}
|
}
|
||||||
|
if (waves[i].gpioOff && !waves[i].gpioOn)
|
||||||
if (waves[i].gpioOff)
|
|
||||||
{
|
{
|
||||||
waveSetOOL(botOOL, waves[i].gpioOff);
|
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->length = 4;
|
||||||
p->next = waveCbPOadr(botCB);
|
p->next = waveCbPOadr(botCB);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (waves[i].flags & WAVE_FLAG_READ)
|
if (waves[i].flags & WAVE_FLAG_READ)
|
||||||
{
|
{
|
||||||
p = rawWaveCBAdr(botCB++);
|
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 (p != NULL)
|
||||||
{
|
{
|
||||||
if (wave_mode == PI_WAVE_MODE_ONE_SHOT)
|
if (wave_mode == PI_WAVE_MODE_ONE_SHOT)
|
||||||
|
@ -3324,9 +3382,7 @@ int rawWaveAddGeneric(unsigned numIn1, rawWave_t *in1)
|
||||||
|
|
||||||
cbs += waveDelayCBs(tDelay);
|
cbs += waveDelayCBs(tDelay);
|
||||||
|
|
||||||
if (out[outPos].gpioOn) cbs++; /* one cb if gpio on */
|
if (out[outPos].gpioOn || out[outPos].gpioOff) cbs++;
|
||||||
|
|
||||||
if (out[outPos].gpioOff) cbs++; /* one cb if gpio off */
|
|
||||||
|
|
||||||
if (out[outPos].flags & WAVE_FLAG_READ)
|
if (out[outPos].flags & WAVE_FLAG_READ)
|
||||||
{
|
{
|
||||||
|
@ -9566,7 +9622,7 @@ int gpioWaveCreate(void)
|
||||||
|
|
||||||
/* What resources are needed? */
|
/* What resources are needed? */
|
||||||
|
|
||||||
waveCBsOOLs(&numCB, &numBOOL, &numTOOL);
|
waveCBsOOLs(&numCB, &numBOOL, &numTOOL);
|
||||||
|
|
||||||
wid = -1;
|
wid = -1;
|
||||||
|
|
||||||
|
@ -9589,10 +9645,10 @@ int gpioWaveCreate(void)
|
||||||
{
|
{
|
||||||
/* Are there enough spare resources? */
|
/* Are there enough spare resources? */
|
||||||
|
|
||||||
if ((numCB+waveOutBotCB) >= NUM_WAVE_CBS)
|
if ((numCB+waveOutBotCB) > NUM_WAVE_CBS)
|
||||||
return PI_TOO_MANY_CBS;
|
return PI_TOO_MANY_CBS;
|
||||||
|
|
||||||
if ((numBOOL+waveOutBotOOL) >= (waveOutTopOOL-numTOOL))
|
if ((numBOOL+waveOutBotOOL) > (waveOutTopOOL-numTOOL))
|
||||||
return PI_TOO_MANY_OOL;
|
return PI_TOO_MANY_OOL;
|
||||||
|
|
||||||
if (wid >= PI_MAX_WAVES)
|
if (wid >= PI_MAX_WAVES)
|
||||||
|
@ -9619,7 +9675,7 @@ int gpioWaveCreate(void)
|
||||||
BOOL = waveInfo[wid].botOOL;
|
BOOL = waveInfo[wid].botOOL;
|
||||||
TOOL = waveInfo[wid].topOOL;
|
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. */
|
/* Sanity check. */
|
||||||
|
|
||||||
|
@ -9633,6 +9689,9 @@ int gpioWaveCreate(void)
|
||||||
numTOOL, waveInfo[wid].topOOL-TOOL);
|
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;
|
waveInfo[wid].deleted = 0;
|
||||||
|
|
||||||
/* Consume waves. */
|
/* Consume waves. */
|
||||||
|
@ -9646,6 +9705,124 @@ int gpioWaveCreate(void)
|
||||||
return wid;
|
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)
|
int gpioWaveDelete(unsigned wave_id)
|
||||||
|
|
34
pigpio.h
34
pigpio.h
|
@ -1986,6 +1986,39 @@ Returns the new waveform id if OK, otherwise PI_EMPTY_WAVEFORM,
|
||||||
PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
|
PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
|
||||||
D*/
|
D*/
|
||||||
|
|
||||||
|
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, the percent of 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.
|
||||||
|
|
||||||
|
Step 1. [*gpioWaveClear*] to clear all waveforms and added data.
|
||||||
|
|
||||||
|
Step 2. [*gpioWaveAdd*] calls to supply the waveform data.
|
||||||
|
|
||||||
|
Step 3. gpioWaveCreatePad(50,50,0) to create a 50% padded waveform and get a unique id
|
||||||
|
|
||||||
|
Step 4. [*gpioWaveTxSend*] with the wave id and PI_WAVE_MODE_ONE_SHOT_SYNC.
|
||||||
|
|
||||||
|
Repeat steps 2-4 as needed always waiting for the active waveform to be transmitted
|
||||||
|
before marking it as deleted.
|
||||||
|
D*/
|
||||||
|
|
||||||
/*F*/
|
/*F*/
|
||||||
int gpioWaveDelete(unsigned wave_id);
|
int gpioWaveDelete(unsigned wave_id);
|
||||||
|
@ -6271,6 +6304,7 @@ PARAMS*/
|
||||||
#define PI_CMD_EVT 116
|
#define PI_CMD_EVT 116
|
||||||
|
|
||||||
#define PI_CMD_PROCU 117
|
#define PI_CMD_PROCU 117
|
||||||
|
#define PI_CMD_WVCAP 118
|
||||||
|
|
||||||
/*DEF_E*/
|
/*DEF_E*/
|
||||||
|
|
||||||
|
|
37
pigpio.py
37
pigpio.py
|
@ -571,6 +571,7 @@ _PI_CMD_EVM =115
|
||||||
_PI_CMD_EVT =116
|
_PI_CMD_EVT =116
|
||||||
|
|
||||||
_PI_CMD_PROCU=117
|
_PI_CMD_PROCU=117
|
||||||
|
_PI_CMD_WVCAP=118
|
||||||
|
|
||||||
# pigpio error numbers
|
# pigpio error numbers
|
||||||
|
|
||||||
|
@ -2304,6 +2305,42 @@ class pi():
|
||||||
"""
|
"""
|
||||||
return _u2i(_pigpio_command(self.sl, _PI_CMD_WVCRE, 0, 0))
|
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.
|
||||||
|
|
||||||
|
. .
|
||||||
|
pi: >=0 (as returned by [*pigpio_start*]).
|
||||||
|
. .
|
||||||
|
|
||||||
|
The data provided by the [*wave_add_**] functions is consumed by this
|
||||||
|
function.
|
||||||
|
|
||||||
|
As many waveforms may be created as there is space available. The
|
||||||
|
wave id is passed to [*wave_send_**] to specify the waveform to transmit.
|
||||||
|
|
||||||
|
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 available resources.
|
||||||
|
This buffer structure allows the transmission of infinite wave sequences.
|
||||||
|
|
||||||
|
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 50% padded waveform and get a unique id
|
||||||
|
|
||||||
|
Step 4. [*wave_send_**] with the id of the waveform to transmit.
|
||||||
|
|
||||||
|
Repeat steps 2-4 as needed always waiting for the active waveform to be transmitted
|
||||||
|
before marking it as deleted.
|
||||||
|
"""
|
||||||
|
return _u2i(_pigpio_command(self.sl, _PI_CMD_WVCAP, percent, 0))
|
||||||
|
|
||||||
def wave_delete(self, wave_id):
|
def wave_delete(self, wave_id):
|
||||||
"""
|
"""
|
||||||
This function deletes the waveform with id wave_id.
|
This function deletes the waveform with id wave_id.
|
||||||
|
|
|
@ -953,6 +953,9 @@ int wave_add_serial(
|
||||||
int wave_create(int pi)
|
int wave_create(int pi)
|
||||||
{return pigpio_command(pi, PI_CMD_WVCRE, 0, 0, 1);}
|
{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)
|
int wave_delete(int pi, unsigned wave_id)
|
||||||
{return pigpio_command(pi, PI_CMD_WVDEL, wave_id, 0, 1);}
|
{return pigpio_command(pi, PI_CMD_WVDEL, wave_id, 0, 1);}
|
||||||
|
|
||||||
|
|
|
@ -1371,6 +1371,43 @@ Returns the new waveform id if OK, otherwise PI_EMPTY_WAVEFORM,
|
||||||
PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
|
PI_NO_WAVEFORM_ID, PI_TOO_MANY_CBS, or PI_TOO_MANY_OOL.
|
||||||
D*/
|
D*/
|
||||||
|
|
||||||
|
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. 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.
|
||||||
|
|
||||||
|
. .
|
||||||
|
pi: >=0 (as returned by [*pigpio_start*]).
|
||||||
|
. .
|
||||||
|
|
||||||
|
The data provided by the [*wave_add_**] functions is consumed by this
|
||||||
|
function.
|
||||||
|
|
||||||
|
As many waveforms may be created as there is space available. The
|
||||||
|
wave id is passed to [*wave_send_**] to specify the waveform to transmit.
|
||||||
|
|
||||||
|
A usage would be the creation of two waves where one is filled while the other
|
||||||
|
is beeing transmitted. Each wave is assigned 50% of the available resources.
|
||||||
|
This buffer structure allows the transmission of infinite wave sequences.
|
||||||
|
|
||||||
|
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 50% padded waveform and get a unique id
|
||||||
|
|
||||||
|
Step 4. [*wave_send_**] with the id of the waveform to transmit.
|
||||||
|
|
||||||
|
Repeat steps 2-4 as needed always waiting for the active waveform to be transmitted
|
||||||
|
before marking it as deleted.
|
||||||
|
|
||||||
|
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*/
|
/*F*/
|
||||||
int wave_delete(int pi, unsigned wave_id);
|
int wave_delete(int pi, unsigned wave_id);
|
||||||
|
|
45
x_pigpio.c
45
x_pigpio.c
|
@ -459,6 +459,51 @@ To the lascivious pleasing of a lute.\n\
|
||||||
|
|
||||||
c = gpioWaveGetMaxCbs();
|
c = gpioWaveGetMaxCbs();
|
||||||
CHECK(5, 21, c, 25016, 0, "wave get max cbs");
|
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;
|
int t6_count;
|
||||||
|
|
41
x_pigpio.py
41
x_pigpio.py
|
@ -483,6 +483,47 @@ To the lascivious pleasing of a lute.
|
||||||
e = pi.wave_delete(0)
|
e = pi.wave_delete(0)
|
||||||
CHECK(5, 33, e, 0, 0, "wave delete")
|
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()
|
t5cb.cancel()
|
||||||
|
|
||||||
t6_count=0
|
t6_count=0
|
||||||
|
|
|
@ -434,6 +434,50 @@ To the lascivious pleasing of a lute.\n\
|
||||||
CHECK(5, 21, c, 25016, 0, "wave get max cbs");
|
CHECK(5, 21, c, 25016, 0, "wave get max cbs");
|
||||||
|
|
||||||
callback_cancel(id);
|
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;
|
int t6_count=0;
|
||||||
|
|
20
x_pigs
20
x_pigs
|
@ -308,3 +308,23 @@ if [[ $s -ge 310 ]]; then echo "WVSP-b ok"; else echo "WVSP-b fail ($s)"; fi
|
||||||
s=$(pigs wvsp 2)
|
s=$(pigs wvsp 2)
|
||||||
if [[ $s = 12000 ]]; then echo "WVSP-c ok"; else echo "WVSP-c fail ($s)"; fi
|
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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue