diff --git a/demos/modules/gaudio/oscilloscope/gwinosc.c b/demos/modules/gaudio/oscilloscope/gwinosc.c index 21a83760..9d095c86 100644 --- a/demos/modules/gaudio/oscilloscope/gwinosc.c +++ b/demos/modules/gaudio/oscilloscope/gwinosc.c @@ -96,7 +96,7 @@ GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint void gwinScopeWaitForTrace(GHandle gh) { #define gs ((GScopeObject *)(gh)) - GAudioData *paud; + GDataBuffer *paud; int i; coord_t x, y; coord_t yoffset; @@ -216,6 +216,6 @@ void gwinScopeWaitForTrace(GHandle gh) { gs->scopemin = scopemin; #endif - gaudioReleaseBuffer(paud); + gfxBufferRelease(paud); #undef gs } diff --git a/demos/modules/gaudio/oscilloscope/main.c b/demos/modules/gaudio/oscilloscope/main.c index b44b5a02..a0b9320e 100644 --- a/demos/modules/gaudio/oscilloscope/main.c +++ b/demos/modules/gaudio/oscilloscope/main.c @@ -58,7 +58,7 @@ int main(void) { // Allocate audio buffers - 4 x 128 byte buffers. // You may need to increase this for slower cpu's. // You may be able to decrease this for low latency operating systems. - gaudioAllocBuffers(4, 128); + gfxBufferAlloc(4, 128); /* Get the screen dimensions */ swidth = gdispGetWidth(); diff --git a/demos/modules/gaudio/play-wave/main.c b/demos/modules/gaudio/play-wave/main.c index f15ec7a1..855c39ff 100644 --- a/demos/modules/gaudio/play-wave/main.c +++ b/demos/modules/gaudio/play-wave/main.c @@ -64,7 +64,7 @@ int main(void) { // Allocate audio buffers - 4 x 512 byte buffers. // You may need to increase this for slower cpu's. // You may be able to decrease this for low latency operating systems. - if (!gaudioAllocBuffers(4, 512)) { + if (!gfxBufferAlloc(4, 512)) { errmsg = "Err: No Memory"; goto theend; } @@ -164,7 +164,7 @@ int main(void) { gdispDrawString(0, gdispGetHeight()/2, "Playing...", font, Yellow); while(toplay) { // Get a buffer to put the data into - paud = gaudioGetBuffer(TIME_INFINITE); // This should never fail as we are waiting forever + paud = gfxBufferGet(TIME_INFINITE); // This should never fail as we are waiting forever // How much data can we put in len = toplay > paud->size ? paud->size : toplay; diff --git a/drivers/gaudio/Win32/gaudio_play_lld.c b/drivers/gaudio/Win32/gaudio_play_lld.c index 6b4f2dab..35a1fc99 100644 --- a/drivers/gaudio/Win32/gaudio_play_lld.c +++ b/drivers/gaudio/Win32/gaudio_play_lld.c @@ -47,7 +47,7 @@ static DWORD threadID; *************************************************************************/ static bool_t senddata(WAVEHDR *pwh) { - GAudioData *paud; + GDataBuffer *paud; // Get the next data block to send gfxSystemLock(); @@ -94,7 +94,7 @@ static DWORD WINAPI waveProc(LPVOID arg) { // Give the buffer back to the Audio Free List gfxSystemLock(); - gaudioPlayReleaseDataBlockI((GAudioData *)pwh->dwUser); + gaudioPlayReleaseDataBlockI((GDataBuffer *)pwh->dwUser); gfxSystemUnlock(); pwh->lpData = 0; nQueuedBuffers--; diff --git a/drivers/gaudio/Win32/gaudio_record_lld.c b/drivers/gaudio/Win32/gaudio_record_lld.c index 259707e3..9f63ff2f 100644 --- a/drivers/gaudio/Win32/gaudio_record_lld.c +++ b/drivers/gaudio/Win32/gaudio_record_lld.c @@ -47,7 +47,7 @@ static DWORD threadID; *************************************************************************/ static bool_t getbuffer(WAVEHDR *pwh) { - GAudioData *paud; + GDataBuffer *paud; // Get the next data block to send gfxSystemLock(); @@ -81,7 +81,7 @@ static bool_t getbuffer(WAVEHDR *pwh) { static DWORD WINAPI waveProc(LPVOID arg) { MSG msg; WAVEHDR *pwh; - GAudioData *paud; + GDataBuffer *paud; (void) arg; while (GetMessage(&msg, 0, 0, 0)) { @@ -93,7 +93,7 @@ static DWORD WINAPI waveProc(LPVOID arg) { waveInUnprepareHeader(ah, pwh, sizeof(WAVEHDR)); // Save the buffer in the audio record list - paud = (GAudioData *)pwh->dwUser; + paud = (GDataBuffer *)pwh->dwUser; paud->len = pwh->dwBytesRecorded; gfxSystemLock(); gaudioRecordSaveDataBlockI(paud); diff --git a/gfxconf.example.h b/gfxconf.example.h index 99f5e569..05f9fd88 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -175,7 +175,7 @@ #define GQUEUE_NEED_ASYNC FALSE #define GQUEUE_NEED_GSYNC FALSE #define GQUEUE_NEED_FSYNC FALSE - +#define GQUEUE_NEED_BUFFERS FALSE /////////////////////////////////////////////////////////////////////////// // GINPUT // diff --git a/src/gaudio/driver_play.h b/src/gaudio/driver_play.h index 72ad4747..d140c2c9 100644 --- a/src/gaudio/driver_play.h +++ b/src/gaudio/driver_play.h @@ -42,19 +42,19 @@ extern "C" { * @iclass * @notapi */ -GAudioData *gaudioPlayGetDataBlockI(void); +GDataBuffer *gaudioPlayGetDataBlockI(void); /** * @brief Release a block of audio data to the free list * - * @param[in] paud The GAudioData block to be released. + * @param[in] paud The GDataBuffer block to be released. * * @note Defined in the high level GAUDIO code for use by the GAUDIO play drivers. * * @iclass * @notapi */ -void gaudioPlayReleaseDataBlockI(GAudioData *paud); +void gaudioPlayReleaseDataBlockI(GDataBuffer *paud); /** * @brief Signal that all playing has now stopped diff --git a/src/gaudio/driver_record.h b/src/gaudio/driver_record.h index 252cae5c..20136dd7 100644 --- a/src/gaudio/driver_record.h +++ b/src/gaudio/driver_record.h @@ -34,19 +34,19 @@ * @iclass * @notapi */ -GAudioData *gaudioRecordGetFreeBlockI(void); +#define gaudioRecordGetFreeBlockI() gfxBufferGetI() /** * @brief Save a block of recorded audio data ready for the application * - * @param[in] paud The GAudioData block with data. + * @param[in] paud The GDataBuffer block with data. * * @note Defined in the high level GAUDIO code for use by the GAUDIO record drivers. * * @iclass * @notapi */ -void gaudioRecordSaveDataBlockI(GAudioData *paud); +void gaudioRecordSaveDataBlockI(GDataBuffer *paud); /** * @brief Signal that all recording has now stopped diff --git a/src/gaudio/gaudio.c b/src/gaudio/gaudio.c index a83dcd85..ee5cfce0 100644 --- a/src/gaudio/gaudio.c +++ b/src/gaudio/gaudio.c @@ -16,8 +16,6 @@ #if GFX_USE_GAUDIO -static gfxQueueGSync freeList; - #if GAUDIO_NEED_PLAY #include "src/gaudio/driver_play.h" @@ -51,7 +49,6 @@ static gfxQueueGSync freeList; void _gaudioInit(void) { - gfxQueueGSyncInit(&freeList); #if GAUDIO_NEED_PLAY gfxQueueASyncInit(&playList); #if GFX_USE_GEVENT @@ -70,48 +67,20 @@ void _gaudioInit(void) void _gaudioDeinit(void) { #if GAUDIO_NEED_PLAY + gfxQueueASyncDeinit(&playList); #if GFX_USE_GEVENT gtimerDeinit(&playTimer); #endif gfxSemDestroy(&playComplete); #endif #if GAUDIO_NEED_RECORD + gfxQueueGSyncDeinit(&recordList); #if GFX_USE_GEVENT gtimerDeinit(&recordTimer); #endif #endif } -bool_t gaudioAllocBuffers(unsigned num, size_t size) { - GAudioData *paud; - - if (num < 1) - return FALSE; - - // Round up to a multiple of 4 to prevent problems with structure alignment - size = (size + 3) & ~0x03; - - // Allocate the memory - if (!(paud = gfxAlloc((size+sizeof(GAudioData)) * num))) - return FALSE; - - // Add each of them to our free list - for(;num--; paud = (GAudioData *)((char *)(paud+1)+size)) { - paud->size = size; - gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud); - } - - return TRUE; -} - -void gaudioReleaseBuffer(GAudioData *paud) { - gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud); -} - -GAudioData *gaudioGetBuffer(delaytime_t ms) { - return (GAudioData *)gfxQueueGSyncGet(&freeList, ms); -} - #if GAUDIO_NEED_PLAY bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) { @@ -123,11 +92,11 @@ GAudioData *gaudioGetBuffer(delaytime_t ms) { return TRUE; } - void gaudioPlay(GAudioData *paud) { + void gaudioPlay(GDataBuffer *pd) { if (!(playFlags & PLAYFLG_ISINIT)) { // Oops - init failed - return it directly to the free-list - if (paud) { - gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud); + if (pd) { + gfxBufferRelease(pd); gfxYield(); // Make sure we get no endless cpu hogging loops } return; @@ -145,12 +114,12 @@ GAudioData *gaudioGetBuffer(delaytime_t ms) { } void gaudioPlayStop(void) { - GAudioData *paud; + GDataBuffer *pd; if (playFlags & PLAYFLG_PLAYING) gaudio_play_lld_stop(); - while((paud = (GAudioData *)gfxQueueASyncGet(&playList))) - gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud); + while((pd = (GDataBuffer *)gfxQueueASyncGet(&playList))) + gfxBufferRelease(pd); } bool_t gaudioPlaySetVolume(uint8_t vol) { @@ -182,7 +151,7 @@ GAudioData *gaudioGetBuffer(delaytime_t ms) { psl->srcflags = 0; if ((playFlags & PLAYFLG_PLAYING)) pe->flags |= GAUDIO_PLAY_PLAYING; - if (!gfxQueueGSyncIsEmpty(&freeList)) + if (gfxBufferIsAvailable()) pe->flags |= GAUDIO_PLAY_FREEBLOCK; geventSendEvent(psl); } @@ -200,12 +169,12 @@ GAudioData *gaudioGetBuffer(delaytime_t ms) { * Routines provided for use by drivers. */ - GAudioData *gaudioPlayGetDataBlockI(void) { - return (GAudioData *)gfxQueueASyncGetI(&playList); + GDataBuffer *gaudioPlayGetDataBlockI(void) { + return (GDataBuffer *)gfxQueueASyncGetI(&playList); } - void gaudioPlayReleaseDataBlockI(GAudioData *paud) { - gfxQueueGSyncPutI(&freeList, (gfxQueueGSyncItem *)paud); + void gaudioPlayReleaseDataBlockI(GDataBuffer *pd) { + gfxBufferReleaseI(pd); #if GFX_USE_GEVENT if (playFlags & PLAYFLG_USEEVENTS) gtimerJabI(&playTimer); @@ -242,17 +211,17 @@ GAudioData *gaudioGetBuffer(delaytime_t ms) { } void gaudioRecordStop(void) { - GAudioData *paud; + GDataBuffer *pd; if ((recordFlags & (RECORDFLG_RECORDING|RECORDFLG_STALLED)) == RECORDFLG_RECORDING) gaudio_record_lld_stop(); recordFlags &= ~(RECORDFLG_RECORDING|RECORDFLG_STALLED); - while((paud = (GAudioData *)gfxQueueGSyncGet(&recordList, TIME_IMMEDIATE))) - gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud); + while((pd = (GDataBuffer *)gfxQueueGSyncGet(&recordList, TIME_IMMEDIATE))) + gfxBufferRelease(pd); } - GAudioData *gaudioRecordGetData(delaytime_t ms) { - return (GAudioData *)gfxQueueGSyncGet(&recordList, ms); + GDataBuffer *gaudioRecordGetData(delaytime_t ms) { + return (GDataBuffer *)gfxQueueGSyncGet(&recordList, ms); } #if GFX_USE_GEVENT @@ -276,7 +245,7 @@ GAudioData *gaudioGetBuffer(delaytime_t ms) { if ((recordFlags & RECORDFLG_STALLED)) pe->flags |= GAUDIO_RECORD_STALL; if (!gfxQueueGSyncIsEmpty(&recordList)) - pe->flags |= GAUDIO_RECORD_GOTBLOCK; + pe->flags |= GAUDIO_RECORD_GOTBUFFER; geventSendEvent(psl); } } @@ -293,11 +262,7 @@ GAudioData *gaudioGetBuffer(delaytime_t ms) { * Routines provided for use by drivers. */ - GAudioData *gaudioRecordGetFreeBlockI(void) { - return (GAudioData *)gfxQueueGSyncGetI(&freeList); - } - - void gaudioRecordSaveDataBlockI(GAudioData *paud) { + void gaudioRecordSaveDataBlockI(GDataBuffer *paud) { gfxQueueGSyncPutI(&recordList, (gfxQueueGSyncItem *)paud); #if GFX_USE_GEVENT if (recordFlags & RECORDFLG_USEEVENTS) diff --git a/src/gaudio/sys_defs.h b/src/gaudio/sys_defs.h index a9a951b7..2bd0e2c8 100644 --- a/src/gaudio/sys_defs.h +++ b/src/gaudio/sys_defs.h @@ -34,19 +34,6 @@ /* Type definitions */ /*===========================================================================*/ -/** - * @brief Contains Audio Data Samples - * @note This structure is followed immediately by the sample data itself. - * When allocating the buffers for the sample data put this structure - * at the beginning of the buffer. - */ -typedef struct GAudioData { - gfxQueueASyncItem next; // @< Used for queuing the buffers - size_t size; // @< The size of the buffer area following this structure (in bytes) - size_t len; // @< The length of the data in the buffer area (in bytes) -} GAudioData; - - // Event types for GAUDIO #define GEVENT_AUDIO_PLAY (GEVENT_GAUDIO_FIRST+0) #define GEVENT_AUDIO_RECORD (GEVENT_GAUDIO_FIRST+1) @@ -95,7 +82,7 @@ typedef struct GAudioData { */ #define GAUDIO_RECORD_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */ #define GAUDIO_RECORD_RECORDING 0x0002 /**< @brief The audio recording system is currently recording */ - #define GAUDIO_RECORD_GOTBLOCK 0x0004 /**< @brief An audio buffer is ready for processing */ + #define GAUDIO_RECORD_GOTBUFFER 0x0004 /**< @brief An audio buffer is ready for processing */ #define GAUDIO_RECORD_STALL 0x0008 /**< @brief The recording process has stalled due to no free buffers */ /** @} */ } GEventAudioRecord; @@ -110,41 +97,6 @@ typedef struct GAudioData { extern "C" { #endif -/** - * @brief Allocate some audio buffers and put them on the free list - * @return TRUE is it succeeded. FALSE on allocation failure. - * - * @param[in] num The number of buffers to allocate - * @param[in] size The size (in bytes) of each buffer - * - * @api - */ -bool_t gaudioAllocBuffers(unsigned num, size_t size); - -/** - * @brief Get an audio buffer from the free list - * @return A GAudioData pointer or NULL if the timeout is exceeded - * - * @params[in] ms The maximum amount of time in milliseconds to wait for a buffer if one is not available. - * - * @api - */ -GAudioData *gaudioGetBuffer(delaytime_t ms); - -/** - * @brief Release a buffer back to the free list - * - * @param[in] paud The buffer to put (back) on the free-list. - * - * @note This call should be used to return any buffers that were taken from - * the free-list once they have been finished with. It can also be used - * to put new buffers onto the free-list. Just make sure the "size" field - * of the GAudioData structure has been filled in first. - * - * @api - */ -void gaudioReleaseBuffer(GAudioData *paud); - #if GAUDIO_NEED_PLAY || defined(__DOXYGEN__) /** * @brief Set the audio device to play on the specified channel and with the specified @@ -172,7 +124,7 @@ void gaudioReleaseBuffer(GAudioData *paud); * @param[in] paud The audio sample buffer to play. It can be NULL (used to restart paused audio) * * @note Calling this will cancel any pause. - * @note Before calling this function the len field of the GAudioData structure must be + * @note Before calling this function the len field of the GDataBuffer structure must be * specified (in bytes). * @note For stereo channels the sample data is interleaved in the buffer. * @note This call returns before the data has completed playing. Subject to available buffers (which @@ -182,7 +134,7 @@ void gaudioReleaseBuffer(GAudioData *paud); * * @api */ - void gaudioPlay(GAudioData *paud); + void gaudioPlay(GDataBuffer *paud); /** * @brief Pause any currently playing sounds. @@ -298,16 +250,20 @@ void gaudioReleaseBuffer(GAudioData *paud); /** * @brief Get a filled audio buffer from the recording list - * @return A GAudioData pointer or NULL if the timeout is exceeded + * @return A GDataBuffer pointer or NULL if the timeout is exceeded * * @params[in] ms The maximum amount of time in milliseconds to wait for data if some is not currently available. * * @note After processing the audio data, your application must return the buffer to the free-list so that * it can be used to record more audio into. This can be done via the play list using @p gaudioPlay() or - * directly using @p gaudioReleaseBuffer(). + * directly using @p gfxBufferRelease(). + * @note A buffer may be returned to the free-list before you have finished processing it provided you finish + * processing it before GADC re-uses it. This is useful when RAM usage is critical to reduce the number + * of buffers required. It works before the free list is a FIFO queue and therefore buffers are kept + * in the queue as long as possible before they are re-used. * @api */ - GAudioData *gaudioRecordGetData(delaytime_t ms); + GDataBuffer *gaudioRecordGetData(delaytime_t ms); #if GFX_USE_GEVENT || defined(__DOXYGEN__) /** diff --git a/src/gaudio/sys_rules.h b/src/gaudio/sys_rules.h index a3f0dffc..4786fa5f 100644 --- a/src/gaudio/sys_rules.h +++ b/src/gaudio/sys_rules.h @@ -27,17 +27,19 @@ #undef GFX_USE_GQUEUE #define GFX_USE_GQUEUE TRUE #endif - #if !GQUEUE_NEED_ASYNC + #if GAUDIO_NEED_PLAY && !GQUEUE_NEED_ASYNC #if GFX_DISPLAY_RULE_WARNINGS - #warning "GAUDIO: GQUEUE_NEED_ASYNC is required if GFX_USE_GAUDIO is TRUE. It has been turned on for you." + #warning "GAUDIO: GQUEUE_NEED_ASYNC is required if GAUDIO_NEED_PLAY is TRUE. It has been turned on for you." #endif #undef GQUEUE_NEED_ASYNC #define GQUEUE_NEED_ASYNC TRUE #endif - #if !GQUEUE_NEED_GSYNC + #if !GQUEUE_NEED_GSYNC || !GQUEUE_NEED_BUFFERS #if GFX_DISPLAY_RULE_WARNINGS - #warning "GAUDIO: GQUEUE_NEED_GSYNC is required if GFX_USE_GAUDIO is TRUE. It has been turned on for you." + #warning "GAUDIO: GQUEUE_NEED_BUFFERS and GQUEUE_NEED_GSYNC are required if GFX_USE_GAUDIO is TRUE. They have been turned on for you." #endif + #undef GQUEUE_NEED_BUFFERS + #define GQUEUE_NEED_BUFFERS TRUE #undef GQUEUE_NEED_GSYNC #define GQUEUE_NEED_GSYNC TRUE #endif diff --git a/src/gfx.c b/src/gfx.c index 8e92fc29..b291a736 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -48,6 +48,10 @@ extern void _gosDeinit(void); extern void _gaudioInit(void); extern void _gaudioDeinit(void); #endif +#if GFX_USE_GQUEUE + extern void _gqueueInit(void); + extern void _gqueueDeinit(void); +#endif #if GFX_USE_GMISC extern void _gmiscInit(void); extern void _gmiscDeinit(void); @@ -63,6 +67,9 @@ void gfxInit(void) // These must be initialised in the order of their dependancies _gosInit(); + #if GFX_USE_GQUEUE + _gqueueInit(); + #endif #if GFX_USE_GMISC _gmiscInit(); #endif @@ -118,7 +125,10 @@ void gfxDeinit(void) _geventDeinit(); #endif #if GFX_USE_GMISC - _gmiscInit(); + _gmiscDeinit(); + #endif + #if GFX_USE_GQUEUE + _gqueueDeinit(); #endif _gosDeinit(); } diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c index b7ecb032..1b2d4618 100644 --- a/src/gqueue/gqueue.c +++ b/src/gqueue/gqueue.c @@ -14,6 +14,21 @@ #if GFX_USE_GQUEUE +#if GQUEUE_NEED_BUFFERS + static gfxQueueGSync bufferFreeList; +#endif + +void _gqueueInit(void) +{ + #if GQUEUE_NEED_BUFFERS + gfxQueueGSyncInit(&bufferFreeList); + #endif +} + +void _gqueueDeinit(void) +{ +} + #if GQUEUE_NEED_ASYNC void gfxQueueASyncInit(gfxQueueASync *pqueue) { pqueue->head = pqueue->tail = 0; @@ -123,6 +138,10 @@ pqueue->head = pqueue->tail = 0; gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT); } + void gfxQueueGSyncDeinit(gfxQueueGSync *pqueue) { + pqueue->head = pqueue->tail = 0; + gfxSemDestroy(&pqueue->sem); + } gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms) { gfxQueueGSyncItem *pi; @@ -232,6 +251,11 @@ pqueue->head = pqueue->tail = 0; gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT); } + void gfxQueueFSyncDeinit(gfxQueueGSync *pqueue) { + while(gfxQueueFSyncGet(pqueue, TIME_IMMEDIATE)); + pqueue->head = pqueue->tail = 0; + gfxSemDestroy(&pqueue->sem); + } gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms) { gfxQueueFSyncItem *pi; @@ -333,4 +357,36 @@ } #endif +#if GQUEUE_NEED_BUFFERS + bool_t gfxBufferAlloc(unsigned num, size_t size) { + GDataBuffer *pd; + + if (num < 1) + return FALSE; + + // Round up to a multiple of 4 to prevent problems with structure alignment + size = (size + 3) & ~0x03; + + // Allocate the memory + if (!(pd = gfxAlloc((size+sizeof(GDataBuffer)) * num))) + return FALSE; + + // Add each of them to our free list + for(;num--; pd = (GDataBuffer *)((char *)(pd+1)+size)) { + pd->size = size; + gfxBufferRelease(pd); + } + + return TRUE; + } + + void gfxBufferRelease(GDataBuffer *pd) { gfxQueueGSyncPut(&bufferFreeList, (gfxQueueGSyncItem *)pd); } + void gfxBufferReleaseI(GDataBuffer *pd) { gfxQueueGSyncPutI(&bufferFreeList, (gfxQueueGSyncItem *)pd); } + GDataBuffer *gfxBufferGet(delaytime_t ms) { return (GDataBuffer *)gfxQueueGSyncGet(&bufferFreeList, ms); } + GDataBuffer *gfxBufferGetI(void) { return (GDataBuffer *)gfxQueueGSyncGetI(&bufferFreeList); } + bool_t gfxBufferIsAvailable(void) { return bufferFreeList.head != 0; } + +#endif + + #endif /* GFX_USE_GQUEUE */ diff --git a/src/gqueue/sys_defs.h b/src/gqueue/sys_defs.h index 4351d4ad..ea3f176e 100644 --- a/src/gqueue/sys_defs.h +++ b/src/gqueue/sys_defs.h @@ -23,6 +23,8 @@ * operations because fully synchronous queues have the highest storage requirements. The other queue types are * optimizations. Efficiency IS important to use (particularly RAM efficiency). * In practice we only implement ASync, GSync and FSync queues as PSync queues are of dubious value. + *
+ * We also define GDataBuffer which is a data buffer that supports being queued. * @{ */ @@ -31,39 +33,13 @@ #if GFX_USE_GQUEUE || defined(__DOXYGEN__) -/** - * @brief A queue - * @{ - */ -typedef struct gfxQueueASync { - struct gfxQueueASyncItem *head; - struct gfxQueueASyncItem *tail; -} gfxQueueASync; - -typedef struct gfxQueueGSync { - struct gfxQueueGSyncItem *head; - struct gfxQueueGSyncItem *tail; - gfxSem sem; -} gfxQueueGSync; - -typedef struct gfxQueueFSync { - struct gfxQueueFSyncItem *head; - struct gfxQueueFSyncItem *tail; - gfxSem sem; -} gfxQueueFSync; -/* @} */ - /** * @brief A queue item * @{ */ typedef struct gfxQueueASyncItem { struct gfxQueueASyncItem *next; -} gfxQueueASyncItem; - -typedef struct gfxQueueGSyncItem { - struct gfxQueueGSyncItem *next; -} gfxQueueGSyncItem; +} gfxQueueASyncItem, gfxQueueGSyncItem; typedef struct gfxQueueFSyncItem { struct gfxQueueFSyncItem *next; @@ -71,6 +47,39 @@ typedef struct gfxQueueFSyncItem { } gfxQueueFSyncItem; /* @} */ +/** + * @brief A queue + * @{ + */ +typedef struct gfxQueueASync { + gfxQueueASyncItem *head; + gfxQueueASyncItem *tail; +} gfxQueueASync; + +typedef struct gfxQueueGSync { + gfxQueueGSyncItem *head; + gfxQueueGSyncItem *tail; + gfxSem sem; +} gfxQueueGSync; + +typedef struct gfxQueueFSync { + gfxQueueFSyncItem *head; + gfxQueueFSyncItem *tail; + gfxSem sem; +} gfxQueueFSync; +/* @} */ + +/** + * @brief A Data Buffer Queue + * @note This structure is followed immediately by the data itself. + * When allocating the buffers for the data put this structure + * at the beginning of the buffer. + */ +typedef struct GDataBuffer { + gfxQueueGSyncItem next; // @< Used for queueing the buffers + size_t size; // @< The size of the buffer area following this structure (in bytes) + size_t len; // @< The length of the data in the buffer area (in bytes) +} GDataBuffer; /*===========================================================================*/ /* Function declarations. */ @@ -97,6 +106,19 @@ void gfxQueueGSyncInit(gfxQueueGSync *pqueue); void gfxQueueFSyncInit(gfxQueueFSync *pqueue); /* @} */ +/** + * @brief De-Initialise a queue. + * + * @param[in] pqueue A pointer to the queue + * + * @api + * @{ + */ +#define gfxQueueASyncDeinit(pqueue) +void gfxQueueGSyncDeinit(gfxQueueGSync *pqueue); +void gfxQueueFSyncDeinit(gfxQueueFSync *pqueue); +/* @} */ + /** * @brief Get an item from the head of the queue (and remove it from the queue). * @return NULL if the timeout expires before an item is available @@ -286,6 +308,58 @@ bool_t gfxQueueFSyncIsInI(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem) #define gfxQueueFSyncNextI(pitem) ((const gfxQueueFSyncItem *)((pitem)->next)) /* @} */ +/** + * @brief Allocate some buffers and put them on the free list + * @return TRUE is it succeeded. FALSE on allocation failure. + * + * @param[in] num The number of buffers to allocate + * @param[in] size The size (in bytes) of each buffer + * + * @api + */ +bool_t gfxBufferAlloc(unsigned num, size_t size); + +/** + * @brief Is there one or more buffers currently available on the free list + * @return TRUE if there are buffers in the free list + * + * @api + * @{ + */ +bool_t gfxBufferIsAvailable(void); +/* @} */ + +/** + * @brief Get a buffer from the free list + * @return A GDataBuffer pointer or NULL if the timeout is exceeded + * + * @params[in] ms The maximum amount of time in milliseconds to wait for a buffer if one is not available. + * + * @api + * @{ + */ +GDataBuffer *gfxBufferGet(delaytime_t ms); +GDataBuffer *gfxBufferGetI(void); +/* @} */ + +/** + * @brief Release a buffer back to the free list + * + * @param[in] pd The buffer to put (back) on the free-list. + * + * @note This call should be used to return any buffers that were taken from + * the free-list once they have been finished with. It can also be used + * to put new buffers onto the free-list. Just make sure the "size" field + * of the GDataBuffer structure has been filled in first. + * + * @api + * @{ + */ +void gfxBufferRelease(GDataBuffer *pd); +void gfxBufferReleaseI(GDataBuffer *pd); +/* @} */ + + #ifdef __cplusplus } #endif diff --git a/src/gqueue/sys_options.h b/src/gqueue/sys_options.h index 7c8627ce..169cf116 100644 --- a/src/gqueue/sys_options.h +++ b/src/gqueue/sys_options.h @@ -41,6 +41,12 @@ #ifndef GQUEUE_NEED_FSYNC #define GQUEUE_NEED_FSYNC FALSE #endif + /** + * @brief Enable Queue-able Data Buffers + */ + #ifndef GQUEUE_NEED_BUFFERS + #define GQUEUE_NEED_BUFFERS FALSE + #endif /** * @} * diff --git a/src/gqueue/sys_rules.h b/src/gqueue/sys_rules.h index baeb073d..831952d8 100644 --- a/src/gqueue/sys_rules.h +++ b/src/gqueue/sys_rules.h @@ -17,6 +17,13 @@ #define _GQUEUE_RULES_H #if GFX_USE_GQUEUE + #if GQUEUE_NEED_BUFFERS && !GQUEUE_NEED_GSYNC + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GQUEUE: GQUEUE_NEED_GSYNC is required if GQUEUE_NEED_BUFFERS is TRUE. It has been turned on for you." + #endif + #undef GQUEUE_NEED_GSYNC + #define GQUEUE_NEED_GSYNC TRUE + #endif #endif #endif /* _GQUEUE_RULES_H */