Allow creation of two waves with 50% padding using gpioWaveCreatePad.

- gpioWaveCreatePad takes three arguments: %CB, %BOOL, %TOOL
- gpioWaveCreatePad checks range of arguments
- gpioWaveCreatePad checks dimension of wave fits inside padding
- wave2Cbs takes three arguments: numCB, numBOOL, numTOOL
- socket command PI_CMD_WVCAP is variadic
This commit is contained in:
Guy McSwain 2020-03-12 09:27:51 -05:00
parent c660e3fc8e
commit 038be60398
4 changed files with 74 additions and 38 deletions

View File

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

View File

@ -2434,7 +2434,26 @@ static int myDoCommand(uintptr_t *p, unsigned bufSize, char *buf)
case PI_CMD_WVCRE: res = gpioWaveCreate(); break;
case PI_CMD_WVCAP: res = gpioWaveCreatePad(p[1]); 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;
@ -2994,7 +3013,8 @@ static void waveCBsOOLs(int *numCBs, int *numBOOLs, int *numTOOLs)
/* ----------------------------------------------------------------------- */
static int wave2Cbs(unsigned wave_mode, int *CB, int *BOOL, int *TOOL, int size)
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;
@ -3132,19 +3152,19 @@ static int wave2Cbs(unsigned wave_mode, int *CB, int *BOOL, int *TOOL, int size)
}
}
if (size)
if (numCB)
{
/* pad the wave */
/* Pad the wave */
botCB = *CB + size - 1;
botOOL = *BOOL + size - 1;
//topOOL = //Fix: Ignore topOOL, flags not supported.
botCB = *CB + numCB - 1;
botOOL = *BOOL + numBOOL - 1;
topOOL = *TOOL - numTOOL;
/* link the last CB to end of wave */
/* Link the last CB to end of wave */
p->next = waveCbPOadr(botCB);
/* add dummy cb at end of DMA */
/* Insert sentinel CB at end of DMA */
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA | DMA_DEST_IGNORE;
@ -9643,7 +9663,7 @@ int gpioWaveCreate(void)
BOOL = waveInfo[wid].botOOL;
TOOL = waveInfo[wid].topOOL;
wave2Cbs(PI_WAVE_MODE_ONE_SHOT, &CB, &BOOL, &TOOL, 0);
wave2Cbs(PI_WAVE_MODE_ONE_SHOT, &CB, &BOOL, &TOOL, 0, 0, 0);
/* Sanity check. */
@ -9673,23 +9693,43 @@ int gpioWaveCreate(void)
return wid;
}
int gpioWaveCreatePad(int percent) // Fix: Make variadic.
int gpioWaveCreatePad(int pctCB, int pctBOOL, int pctTOOL)
{
int i, wid;
int numCB, numBOOL, numTOOL;
int CB, BOOL, TOOL;
DBG(DBG_USER, "");
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)", pctCB);
if (pctTOOL < 0 || pctTOOL > 100)
SOFT_ERROR(PI_BAD_PARAM, "bad wave param, pctTOOL=(%d)", pctCB);
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 -1) * pctCB / 100;
BOOL = (NUM_WAVE_OOL - PI_WAVE_COUNT_PAGES*OOL_PER_OPAGE -1) * pctBOOL /100;
TOOL = (NUM_WAVE_OOL * pctTOOL) / 100;
/* Reject if wave is too big */
if (numCB >= CB) return PI_TOO_MANY_CBS;
if (numBOOL >= BOOL) return PI_I2C_WRITE_FAILED; // Fix
if (numTOOL > TOOL) return PI_I2C_READ_FAILED; // Fix
/* Set the padding */
numCB = CB;
numBOOL = BOOL;
numTOOL = TOOL;
numCB = (NUM_WAVE_CBS * percent) / 100;
numBOOL = (NUM_WAVE_OOL * percent) /100;
numTOOL = 0; // ignore TOOL, ie, no flags support
wid = -1;
@ -9742,7 +9782,7 @@ int gpioWaveCreatePad(int percent) // Fix: Make variadic.
BOOL = waveInfo[wid].botOOL;
TOOL = waveInfo[wid].topOOL;
wave2Cbs(PI_WAVE_MODE_ONE_SHOT, &CB, &BOOL, &TOOL, numCB);
wave2Cbs(PI_WAVE_MODE_ONE_SHOT, &CB, &BOOL, &TOOL, numCB, numBOOL, numTOOL);
/* Sanity check. */

View File

@ -1986,42 +1986,38 @@ 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*/
int gpioWaveCreatePad(int percent);
int gpioWaveCreatePad(int pctCB, int pctBOOL, int pctTOOL);
/*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.
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.
. .
pi: >=0 (as returned by [*pigpio_start*]).
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).
. .
The data provided by the [*wave_add_**] functions is consumed by this
function.
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.
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.
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 beeing transmitted. Each wave is assigned 50% of the available resources.
is being transmitted. Each wave is assigned 50% of the resources.
This buffer structure allows the transmission of infinite wave sequences.
Step 1. [*wave_clear*] to clear all waveforms and added data.
Step 1. [*gpioWaveClear*] to clear all waveforms and added data.
Step 2. [*wave_add_**] calls to supply the waveform data.
Step 2. [*gpioWaveAdd*] calls to supply the waveform data.
Step 3. [*wave_create_and_pad*] to create a 50% padded waveform and get a unique id
Step 3. gpioWaveCreatePad(50,50,0) to create a 50% padded waveform and get a unique id
Step 4. [*wave_send_**] with the id of the waveform to transmit.
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.
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*/

View File

@ -2325,7 +2325,7 @@ class pi():
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.
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.