diff --git a/command.c b/command.c index 0170005..ffc3463 100644 --- a/command.c +++ b/command.c @@ -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. */ diff --git a/pigpio.c b/pigpio.c index 920b9fb..bbac95d 100644 --- a/pigpio.c +++ b/pigpio.c @@ -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. */ diff --git a/pigpio.h b/pigpio.h index da29f1b..bffcd8d 100644 --- a/pigpio.h +++ b/pigpio.h @@ -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*/ diff --git a/pigpio.py b/pigpio.py index fcc54a7..a9f10e3 100644 --- a/pigpio.py +++ b/pigpio.py @@ -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.