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<