aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/modules/gaudio/oscilloscope/gwinosc.c4
-rw-r--r--demos/modules/gaudio/oscilloscope/main.c2
-rw-r--r--demos/modules/gaudio/play-wave/main.c4
-rw-r--r--drivers/gaudio/Win32/gaudio_play_lld.c4
-rw-r--r--drivers/gaudio/Win32/gaudio_record_lld.c6
-rw-r--r--gfxconf.example.h2
-rw-r--r--src/gaudio/driver_play.h6
-rw-r--r--src/gaudio/driver_record.h6
-rw-r--r--src/gaudio/gaudio.c75
-rw-r--r--src/gaudio/sys_defs.h64
-rw-r--r--src/gaudio/sys_rules.h10
-rw-r--r--src/gfx.c12
-rw-r--r--src/gqueue/gqueue.c56
-rw-r--r--src/gqueue/sys_defs.h122
-rw-r--r--src/gqueue/sys_options.h6
-rw-r--r--src/gqueue/sys_rules.h7
16 files changed, 231 insertions, 155 deletions
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.
+ * <br>
+ * We also define GDataBuffer which is a data buffer that supports being queued.
* @{
*/
@@ -32,45 +34,52 @@
#if GFX_USE_GQUEUE || defined(__DOXYGEN__)
/**
+ * @brief A queue item
+ * @{
+ */
+typedef struct gfxQueueASyncItem {
+ struct gfxQueueASyncItem *next;
+} gfxQueueASyncItem, gfxQueueGSyncItem;
+
+typedef struct gfxQueueFSyncItem {
+ struct gfxQueueFSyncItem *next;
+ gfxSem sem;
+} gfxQueueFSyncItem;
+/* @} */
+
+/**
* @brief A queue
* @{
*/
typedef struct gfxQueueASync {
- struct gfxQueueASyncItem *head;
- struct gfxQueueASyncItem *tail;
+ gfxQueueASyncItem *head;
+ gfxQueueASyncItem *tail;
} gfxQueueASync;
typedef struct gfxQueueGSync {
- struct gfxQueueGSyncItem *head;
- struct gfxQueueGSyncItem *tail;
- gfxSem sem;
+ gfxQueueGSyncItem *head;
+ gfxQueueGSyncItem *tail;
+ gfxSem sem;
} gfxQueueGSync;
typedef struct gfxQueueFSync {
- struct gfxQueueFSyncItem *head;
- struct gfxQueueFSyncItem *tail;
- gfxSem sem;
+ gfxQueueFSyncItem *head;
+ gfxQueueFSyncItem *tail;
+ gfxSem sem;
} gfxQueueFSync;
/* @} */
/**
- * @brief A queue item
- * @{
+ * @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 gfxQueueASyncItem {
- struct gfxQueueASyncItem *next;
-} gfxQueueASyncItem;
-
-typedef struct gfxQueueGSyncItem {
- struct gfxQueueGSyncItem *next;
-} gfxQueueGSyncItem;
-
-typedef struct gfxQueueFSyncItem {
- struct gfxQueueFSyncItem *next;
- gfxSem sem;
-} gfxQueueFSyncItem;
-/* @} */
-
+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. */
@@ -98,6 +107,19 @@ 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 */