aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-03-11 17:13:31 +1000
committerinmarket <andrewh@inmarket.com.au>2014-03-11 17:13:31 +1000
commitea5a1b849df6e5085a92957ad387f9e653674415 (patch)
tree72ede5ed78263a6fdba25039398b5c2a55bd1d3a
parent944c33cbff5f2cfb1c80f48193aa2161574864fd (diff)
downloaduGFX-ea5a1b849df6e5085a92957ad387f9e653674415.tar.gz
uGFX-ea5a1b849df6e5085a92957ad387f9e653674415.tar.bz2
uGFX-ea5a1b849df6e5085a92957ad387f9e653674415.zip
Combine GAUDIN and GAUDOUT into a single GAUDIO module.
Simplify GAUDIN (now GAUDIO RECORD) api. Update audio demo's to match. Port Win32 driver to new audio api.
-rw-r--r--boards/base/Olimex-SAM7EX256-GE12/board.mk2
-rw-r--r--boards/base/Olimex-SAM7EX256-GE12/readme.txt2
-rw-r--r--boards/base/Olimex-SAM7EX256-GE8/board.mk2
-rw-r--r--boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h (renamed from boards/base/Olimex-SAM7EX256-GE8/gaudin_lld_board.h)18
-rw-r--r--boards/base/Olimex-SAM7EX256-GE8/readme.txt2
-rw-r--r--boards/base/Win32/board.mk2
-rw-r--r--demos/modules/gaudio/oscilloscope/demo.mk (renamed from demos/modules/audio/oscilloscope/demo.mk)2
-rw-r--r--demos/modules/gaudio/oscilloscope/gfxconf.h (renamed from demos/modules/audio/oscilloscope/gfxconf.h)5
-rw-r--r--demos/modules/gaudio/oscilloscope/gwinosc.c (renamed from demos/modules/audio/oscilloscope/gwinosc.c)175
-rw-r--r--demos/modules/gaudio/oscilloscope/gwinosc.h (renamed from demos/modules/audio/oscilloscope/gwinosc.h)8
-rw-r--r--demos/modules/gaudio/oscilloscope/main.c (renamed from demos/modules/audio/oscilloscope/main.c)12
-rw-r--r--demos/modules/gaudio/oscilloscope/results_264x264.jpg (renamed from demos/modules/audio/oscilloscope/results_264x264.jpg)bin19615 -> 19615 bytes
-rw-r--r--demos/modules/gaudio/play-wave/allwrong.wav (renamed from demos/modules/audio/play-wave/allwrong.wav)bin29434 -> 29434 bytes
-rw-r--r--demos/modules/gaudio/play-wave/demo.mk (renamed from demos/modules/audio/play-wave/demo.mk)2
-rw-r--r--demos/modules/gaudio/play-wave/gfxconf.h (renamed from demos/modules/audio/play-wave/gfxconf.h)5
-rw-r--r--demos/modules/gaudio/play-wave/main.c (renamed from demos/modules/audio/play-wave/main.c)12
-rw-r--r--demos/modules/gaudio/play-wave/romfs_allwrong.h (renamed from demos/modules/audio/play-wave/romfs_allwrong.h)2
-rw-r--r--demos/modules/gaudio/play-wave/romfs_files.h (renamed from demos/modules/audio/play-wave/romfs_files.h)0
-rw-r--r--drivers/audio/Win32/driver.mk6
-rw-r--r--drivers/audio/Win32/gaudin_lld.c170
-rw-r--r--drivers/audio/Win32/gaudin_lld_config.h64
-rw-r--r--drivers/audio/Win32/readme.txt10
-rw-r--r--drivers/audio/gadc/driver.mk5
-rw-r--r--drivers/gaudio/Win32/driver.mk6
-rw-r--r--drivers/gaudio/Win32/gaudio_play_config.h (renamed from drivers/audio/Win32/gaudout_lld_config.h)34
-rw-r--r--drivers/gaudio/Win32/gaudio_play_lld.c (renamed from drivers/audio/Win32/gaudout_lld.c)88
-rw-r--r--drivers/gaudio/Win32/gaudio_record_config.h63
-rw-r--r--drivers/gaudio/Win32/gaudio_record_lld.c187
-rw-r--r--drivers/gaudio/Win32/readme.txt10
-rw-r--r--drivers/gaudio/gadc/driver.mk5
-rw-r--r--drivers/gaudio/gadc/gaudio_record_board_template.h (renamed from drivers/audio/gadc/gaudin_lld_board_template.h)20
-rw-r--r--drivers/gaudio/gadc/gaudio_record_config.h (renamed from drivers/audio/gadc/gaudin_lld_config.h)30
-rw-r--r--drivers/gaudio/gadc/gaudio_record_lld.c (renamed from drivers/audio/gadc/gaudin_lld.c)16
-rw-r--r--drivers/gaudio/gadc/readme.txt (renamed from drivers/audio/gadc/readme.txt)2
-rw-r--r--gfx.h35
-rw-r--r--gfx.mk3
-rw-r--r--gfxconf.example.h13
-rw-r--r--src/gaudin/driver.h102
-rw-r--r--src/gaudin/gaudin.c158
-rw-r--r--src/gaudin/sys_defs.h174
-rw-r--r--src/gaudin/sys_make.mk1
-rw-r--r--src/gaudin/sys_options.h32
-rw-r--r--src/gaudin/sys_rules.h30
-rw-r--r--src/gaudio/driver_play.h (renamed from src/gaudout/driver.h)58
-rw-r--r--src/gaudio/driver_record.h108
-rw-r--r--src/gaudio/gaudio.c318
-rw-r--r--src/gaudio/sys_defs.h340
-rw-r--r--src/gaudio/sys_make.mk1
-rw-r--r--src/gaudio/sys_options.h44
-rw-r--r--src/gaudio/sys_rules.h54
-rw-r--r--src/gaudout/gaudout.c169
-rw-r--r--src/gaudout/sys_defs.h217
-rw-r--r--src/gaudout/sys_make.mk1
-rw-r--r--src/gaudout/sys_options.h32
-rw-r--r--src/gaudout/sys_rules.h44
-rw-r--r--src/gevent/sys_defs.h3
-rw-r--r--src/gfx.c22
57 files changed, 1405 insertions, 1521 deletions
diff --git a/boards/base/Olimex-SAM7EX256-GE12/board.mk b/boards/base/Olimex-SAM7EX256-GE12/board.mk
index a1eae818..2ef53142 100644
--- a/boards/base/Olimex-SAM7EX256-GE12/board.mk
+++ b/boards/base/Olimex-SAM7EX256-GE12/board.mk
@@ -5,4 +5,4 @@ include $(GFXLIB)/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
include $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.mk
include $(GFXLIB)/drivers/ginput/dial/GADC/ginput_lld.mk
include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk
-include $(GFXLIB)/drivers/audio/gadc/driver.mk
+include $(GFXLIB)/drivers/gaudio/gadc/driver.mk
diff --git a/boards/base/Olimex-SAM7EX256-GE12/readme.txt b/boards/base/Olimex-SAM7EX256-GE12/readme.txt
index ebf1497a..83e32ee8 100644
--- a/boards/base/Olimex-SAM7EX256-GE12/readme.txt
+++ b/boards/base/Olimex-SAM7EX256-GE12/readme.txt
@@ -6,7 +6,7 @@ On this board uGFX currently supports:
- GADC via the AT91SAM7 driver
- GINPUT-dials via the GADC driver
- GINPUT-toggles via the Pal driver
- - GAUDIN via the GADC driver
+ - GAUDIO recording via the GADC driver
Note there are two variants of this board - one with the GE8 display
and one with the GE12 display. This one is for the GE12 display.
diff --git a/boards/base/Olimex-SAM7EX256-GE8/board.mk b/boards/base/Olimex-SAM7EX256-GE8/board.mk
index a60d9355..249cfc2d 100644
--- a/boards/base/Olimex-SAM7EX256-GE8/board.mk
+++ b/boards/base/Olimex-SAM7EX256-GE8/board.mk
@@ -5,4 +5,4 @@ include $(GFXLIB)/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
include $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.mk
include $(GFXLIB)/drivers/ginput/dial/GADC/ginput_lld.mk
include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk
-include $(GFXLIB)/drivers/audio/gadc/driver.mk
+include $(GFXLIB)/drivers/gaudio/gadc/driver.mk
diff --git a/boards/base/Olimex-SAM7EX256-GE8/gaudin_lld_board.h b/boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h
index 632f0659..cdea5e06 100644
--- a/boards/base/Olimex-SAM7EX256-GE8/gaudin_lld_board.h
+++ b/boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h
@@ -6,28 +6,28 @@
*/
/**
- * @file boards/base/Olimex-SAM7EX256-GE8/gaudin_lld_board.h
- * @brief GAUDIN Driver board config file for the Olimex SAM7EX256 board
+ * @file boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h
+ * @brief GAUDIO Record Driver board config file for the Olimex SAM7EX256 board
*/
-#ifndef _GAUDIN_LLD_BOARD_H
-#define _GAUDIN_LLD_BOARD_H
+#ifndef _GAUDIO_RECORD_BOARD_H
+#define _GAUDIO_RECORD_BOARD_H
/*===========================================================================*/
/* Audio inputs on this board */
/*===========================================================================*/
-#define GAUDIN_NUM_CHANNELS 1
+#define GAUDIO_RECORD_NUM_CHANNELS 1
/**
* The list of audio channels and their uses
*/
-#define GAUDIN_MICROPHONE 0
+#define GAUDIO_RECORD_MICROPHONE 0
-#ifdef GAUDIN_LLD_IMPLEMENTATION
- static uint32_t gaudin_lld_physdevs[GAUDIN_NUM_CHANNELS] = {
+#ifdef GAUDIO_RECORD_IMPLEMENTATION
+ static uint32_t gaudin_lld_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = {
GADC_PHYSDEV_MICROPHONE,
};
#endif
-#endif /* _GAUDIN_LLD_BOARD_H */
+#endif /* _GAUDIO_RECORD_BOARD_H */
diff --git a/boards/base/Olimex-SAM7EX256-GE8/readme.txt b/boards/base/Olimex-SAM7EX256-GE8/readme.txt
index 01b3f8b4..f613dee3 100644
--- a/boards/base/Olimex-SAM7EX256-GE8/readme.txt
+++ b/boards/base/Olimex-SAM7EX256-GE8/readme.txt
@@ -6,7 +6,7 @@ On this board uGFX currently supports:
- GADC via the AT91SAM7 driver
- GINPUT-dials via the GADC driver
- GINPUT-toggles via the Pal driver
- - GAUDIN via the GADC driver
+ - GAUDIO recording via the GADC driver
Note there are two variants of this board - one with the GE8 display
and one with the GE12 display. This one is for the GE8 display.
diff --git a/boards/base/Win32/board.mk b/boards/base/Win32/board.mk
index 5f624f3d..69d09100 100644
--- a/boards/base/Win32/board.mk
+++ b/boards/base/Win32/board.mk
@@ -2,4 +2,4 @@ GFXINC += $(GFXLIB)/boards/base/Win32
GFXSRC +=
include $(GFXLIB)/drivers/multiple/Win32/driver.mk
-include $(GFXLIB)/drivers/audio/Win32/driver.mk
+include $(GFXLIB)/drivers/gaudio/Win32/driver.mk
diff --git a/demos/modules/audio/oscilloscope/demo.mk b/demos/modules/gaudio/oscilloscope/demo.mk
index ffdf6980..47b28f5f 100644
--- a/demos/modules/audio/oscilloscope/demo.mk
+++ b/demos/modules/gaudio/oscilloscope/demo.mk
@@ -1,3 +1,3 @@
-DEMODIR = $(GFXLIB)/demos/modules/audio/oscilloscope
+DEMODIR = $(GFXLIB)/demos/modules/gaudio/oscilloscope
GFXINC += $(DEMODIR)
GFXSRC += $(DEMODIR)/main.c $(DEMODIR)/gwinosc.c
diff --git a/demos/modules/audio/oscilloscope/gfxconf.h b/demos/modules/gaudio/oscilloscope/gfxconf.h
index 8733268d..2caa1da9 100644
--- a/demos/modules/audio/oscilloscope/gfxconf.h
+++ b/demos/modules/gaudio/oscilloscope/gfxconf.h
@@ -46,11 +46,14 @@
#define GFX_USE_GWIN TRUE
#define GFX_USE_GTIMER TRUE
//#define GFX_USE_GADC TRUE
-#define GFX_USE_GAUDIN TRUE
+#define GFX_USE_GAUDIO TRUE
/* Features for the GDISP sub-system. */
#define GDISP_NEED_VALIDATION TRUE
#define GDISP_NEED_CLIP TRUE
#define GDISP_NEED_MULTITHREAD TRUE
+/* Features for the GAUDIO sub-system */
+#define GAUDIO_NEED_RECORD TRUE
+
#endif /* _GFXCONF_H */
diff --git a/demos/modules/audio/oscilloscope/gwinosc.c b/demos/modules/gaudio/oscilloscope/gwinosc.c
index 43ef1385..21a83760 100644
--- a/demos/modules/audio/oscilloscope/gwinosc.c
+++ b/demos/modules/gaudio/oscilloscope/gwinosc.c
@@ -32,8 +32,8 @@
*
* This GWIN superset implements a simple audio oscilloscope using the GAUDIN module.
*
- * It makes many assumptions, the most fundamental of which is that the audio device
- * produces unsigned integer samples.
+ * It makes many assumptions, the most fundamental of which is that the audio data
+ * should be scaled to SCOPE_Y_BITS.
*
* The GMISC module with GMISC_NEED_ARRAYOPS could be used to process the samples more
* correctly if we were really building something generic.
@@ -45,22 +45,15 @@
/* Include internal GWIN routines so we can build our own superset class */
#include "src/gwin/class_gwin.h"
-/* The size of our dynamically allocated audio buffer */
-#define AUDIOBUFSZ 64*2
-
/* How many flat-line sample before we trigger */
#define FLATLINE_SAMPLES 8
static void _destroy(GHandle gh) {
- gaudinStop();
+ gaudioRecordStop();
if (((GScopeObject *)gh)->lastscopetrace) {
gfxFree(((GScopeObject *)gh)->lastscopetrace);
((GScopeObject *)gh)->lastscopetrace = 0;
}
- if (((GScopeObject *)gh)->audiobuf) {
- gfxFree(((GScopeObject *)gh)->audiobuf);
- ((GScopeObject *)gh)->audiobuf = 0;
- }
}
static const gwinVMT scopeVMT = {
@@ -71,127 +64,136 @@ static const gwinVMT scopeVMT = {
0, // The after-clear routine
};
-GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint16_t channel, uint32_t frequency) {
+GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
+ /* Make sure the audio parameters are valid first */
+ if (!gaudioRecordInit(channel, frequency, format))
+ return 0;
+
/* Initialise the base class GWIN */
if (!(gs = (GScopeObject *)_gwindowCreate(g, &gs->g, pInit, &scopeVMT, 0)))
return 0;
/* Initialise the scope object members and allocate memory for buffers */
- gfxSemInit(&gs->bsem, 0, 1);
+ gs->format = format;
gs->nextx = 0;
if (!(gs->lastscopetrace = (coord_t *)gfxAlloc(gs->g.width * sizeof(coord_t))))
return 0;
- if (!(gs->audiobuf = (audin_sample_t *)gfxAlloc(AUDIOBUFSZ * sizeof(audin_sample_t))))
- return 0;
-#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
- gs->lasty = gs->g.height/2;
-#elif TRIGGER_METHOD == TRIGGER_MINVALUE
- gs->lasty = gs->g.height/2;
- gs->scopemin = 0;
-#endif
-
- /* Start the GADC high speed converter */
- gaudinInit(channel, frequency, gs->audiobuf, AUDIOBUFSZ, AUDIOBUFSZ/2);
- gaudinSetBSem(&gs->bsem, &gs->myEvent);
- gaudinStart();
+ #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
+ gs->lasty = gs->g.height/2;
+ #elif TRIGGER_METHOD == TRIGGER_MINVALUE
+ gs->lasty = gs->g.height/2;
+ gs->scopemin = 0;
+ #endif
+ /* Set visibility */
gwinSetVisible((GHandle)gs, pInit->show);
+
+ /* Start the audio recording */
+ gaudioRecordStart();
+
return (GHandle)gs;
}
void gwinScopeWaitForTrace(GHandle gh) {
#define gs ((GScopeObject *)(gh))
+ GAudioData *paud;
int i;
coord_t x, y;
coord_t yoffset;
- audin_sample_t *pa;
+ uint8_t *pa8;
+ uint16_t *pa16;
coord_t *pc;
-#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
- bool_t rdytrigger;
- int flsamples;
-#elif TRIGGER_METHOD == TRIGGER_MINVALUE
- bool_t rdytrigger;
- int flsamples;
- coord_t scopemin;
-#endif
+ uint8_t shr;
+
+ #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
+ bool_t rdytrigger;
+ int flsamples;
+ #elif TRIGGER_METHOD == TRIGGER_MINVALUE
+ bool_t rdytrigger;
+ int flsamples;
+ coord_t scopemin;
+ #endif
if (gh->vmt != &scopeVMT)
return;
/* Wait for a set of audio conversions */
- gfxSemWait(&gs->bsem, TIME_INFINITE);
+ paud = gaudioRecordGetData(TIME_INFINITE);
/* Ensure we are drawing in the right area */
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
+ shr = 16 - gfxSampleFormatBits(gs->format);
yoffset = gh->height/2;
- if (!(GAUDIN_SAMPLE_FORMAT & 1))
+ if (!gfxSampleFormatIsSigned(gs->format))
yoffset += (1<<SCOPE_Y_BITS)/2;
+
x = gs->nextx;
pc = gs->lastscopetrace+x;
- pa = gs->myEvent.buffer;
-#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
- rdytrigger = FALSE;
- flsamples = 0;
-#elif TRIGGER_METHOD == TRIGGER_MINVALUE
- rdytrigger = FALSE;
- flsamples = 0;
- scopemin = 0;
-#endif
+ pa8 = (uint8_t *)(paud+1);
+ pa16 = (uint16_t *)(paud+1);
+
+ #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
+ rdytrigger = FALSE;
+ flsamples = 0;
+ #elif TRIGGER_METHOD == TRIGGER_MINVALUE
+ rdytrigger = FALSE;
+ flsamples = 0;
+ scopemin = 0;
+ #endif
- for(i = gs->myEvent.count; i; i--) {
+ for(i = paud->len/(gfxSampleFormatBits(gs->format)/8); i; i--) {
/* Calculate the new scope value - re-scale using simple shifts for efficiency, re-center and y-invert */
- #if GAUDIN_BITS_PER_SAMPLE > SCOPE_Y_BITS
- y = yoffset - (*pa++ >> (GAUDIN_BITS_PER_SAMPLE - SCOPE_Y_BITS));
- #else
- y = yoffset - (*pa++ << (SCOPE_Y_BITS - GAUDIN_BITS_PER_SAMPLE));
+ if (gs->format <= 8)
+ y = yoffset - (((coord_t)(*pa8++ ) << shr) >> (16-SCOPE_Y_BITS));
+ else
+ y = yoffset - (((coord_t)(*pa16++) << shr) >> (16-SCOPE_Y_BITS));
+
+ #if TRIGGER_METHOD == TRIGGER_MINVALUE
+ /* Calculate the scopemin ready for the next trace */
+ if (y > scopemin)
+ scopemin = y;
#endif
-#if TRIGGER_METHOD == TRIGGER_MINVALUE
- /* Calculate the scopemin ready for the next trace */
- if (y > scopemin)
- scopemin = y;
-#endif
-
/* Have we reached the end of a scope trace? */
if (x >= gh->width) {
-#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP || TRIGGER_METHOD == TRIGGER_MINVALUE
- /* Handle triggering - we trigger on the next sample minimum (y value maximum) or a flat-line */
-
- #if TRIGGER_METHOD == TRIGGER_MINVALUE
- /* Arm when we reach the sample minimum (y value maximum) of the previous trace */
- if (!rdytrigger && y >= gs->scopemin)
- rdytrigger = TRUE;
- #endif
+ #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP || TRIGGER_METHOD == TRIGGER_MINVALUE
+ /* Handle triggering - we trigger on the next sample minimum (y value maximum) or a flat-line */
- if (y == gs->lasty) {
- /* Trigger if we get too many flat-line samples regardless of the armed state */
- if (++flsamples < FLATLINE_SAMPLES)
- continue;
- flsamples = 0;
- } else if (y > gs->lasty) {
- gs->lasty = y;
- flsamples = 0;
- #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
- /* Arm the trigger when samples fall (y increases) ie. negative slope */
- rdytrigger = TRUE;
+ #if TRIGGER_METHOD == TRIGGER_MINVALUE
+ /* Arm when we reach the sample minimum (y value maximum) of the previous trace */
+ if (!rdytrigger && y >= gs->scopemin)
+ rdytrigger = TRUE;
#endif
- continue;
- } else {
- /* If the trigger is armed, Trigger when samples increases (y decreases) ie. positive slope */
- gs->lasty = y;
- flsamples = 0;
- if (!rdytrigger)
- continue;
- }
- /* Ready for a the next trigger cycle */
- rdytrigger = FALSE;
-#endif
+ if (y == gs->lasty) {
+ /* Trigger if we get too many flat-line samples regardless of the armed state */
+ if (++flsamples < FLATLINE_SAMPLES)
+ continue;
+ flsamples = 0;
+ } else if (y > gs->lasty) {
+ gs->lasty = y;
+ flsamples = 0;
+ #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
+ /* Arm the trigger when samples fall (y increases) ie. negative slope */
+ rdytrigger = TRUE;
+ #endif
+ continue;
+ } else {
+ /* If the trigger is armed, Trigger when samples increases (y decreases) ie. positive slope */
+ gs->lasty = y;
+ flsamples = 0;
+ if (!rdytrigger)
+ continue;
+ }
+
+ /* Ready for a the next trigger cycle */
+ rdytrigger = FALSE;
+ #endif
/* Prepare for a scope trace */
x = 0;
@@ -214,5 +216,6 @@ void gwinScopeWaitForTrace(GHandle gh) {
gs->scopemin = scopemin;
#endif
+ gaudioReleaseBuffer(paud);
#undef gs
}
diff --git a/demos/modules/audio/oscilloscope/gwinosc.h b/demos/modules/gaudio/oscilloscope/gwinosc.h
index 0efb403c..5a5c5034 100644
--- a/demos/modules/audio/oscilloscope/gwinosc.h
+++ b/demos/modules/gaudio/oscilloscope/gwinosc.h
@@ -64,9 +64,7 @@ typedef struct GScopeObject_t {
GWindowObject g; // Base Class
coord_t *lastscopetrace; // To store last scope trace
- gfxSem bsem; // We get signalled on this
- audin_sample_t *audiobuf; // To store audio samples
- GEventAudioIn myEvent; // Information on received samples
+ ArrayDataFormat format; // The sample format
coord_t nextx; // Where we are up to
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
coord_t lasty; // The last y value - used for trigger slope detection
@@ -83,8 +81,8 @@ extern "C" {
/**
* Create a scope window.
*/
- GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint16_t channel, uint32_t frequency);
- #define gwinScopeCreate(gs,pI,ch,f) gwinGScopeCreate(GDISP,gs,pI,ch,f)
+ GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint16_t channel, uint32_t frequency, ArrayDataFormat format);
+ #define gwinScopeCreate(gs,pI,ch,f,fmt) gwinGScopeCreate(GDISP,gs,pI,ch,f,fmt)
/**
* Wait for a scope trace to be ready and then draw it.
diff --git a/demos/modules/audio/oscilloscope/main.c b/demos/modules/gaudio/oscilloscope/main.c
index 32418450..b44b5a02 100644
--- a/demos/modules/audio/oscilloscope/main.c
+++ b/demos/modules/gaudio/oscilloscope/main.c
@@ -39,8 +39,9 @@
#include "gwinosc.h"
/* Specify our timing parameters */
-#define MY_AUDIO_FREQUENCY 4000 /* 4khz */
-#define MY_AUDIO_CHANNEL 0 /* Use channel 0 */
+#define MY_AUDIO_FREQUENCY 8000 /* 8khz. If this is too much try 4000 (4khz) */
+#define MY_AUDIO_CHANNEL 0 /* Use channel 0 - must be a mono channel */
+#define MY_AUDIO_FORMAT GAUDIO_RECORD_FORMAT1 /* The default format */
/* Data */
static GScopeObject gScopeWindow;
@@ -54,6 +55,11 @@ int main(void) {
gfxInit();
+ // 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);
+
/* Get the screen dimensions */
swidth = gdispGetWidth();
sheight = gdispGetHeight();
@@ -65,7 +71,7 @@ int main(void) {
wi.show = TRUE;
wi.x = wi.y = 0;
wi.width = swidth; wi.height = sheight;
- ghScope = gwinScopeCreate(&gScopeWindow, &wi, MY_AUDIO_CHANNEL, MY_AUDIO_FREQUENCY);
+ ghScope = gwinScopeCreate(&gScopeWindow, &wi, MY_AUDIO_CHANNEL, MY_AUDIO_FREQUENCY, MY_AUDIO_FORMAT);
}
gwinSetBgColor(ghScope, White);
gwinSetColor(ghScope, Red);
diff --git a/demos/modules/audio/oscilloscope/results_264x264.jpg b/demos/modules/gaudio/oscilloscope/results_264x264.jpg
index e459f7e1..e459f7e1 100644
--- a/demos/modules/audio/oscilloscope/results_264x264.jpg
+++ b/demos/modules/gaudio/oscilloscope/results_264x264.jpg
Binary files differ
diff --git a/demos/modules/audio/play-wave/allwrong.wav b/demos/modules/gaudio/play-wave/allwrong.wav
index e221ff2f..e221ff2f 100644
--- a/demos/modules/audio/play-wave/allwrong.wav
+++ b/demos/modules/gaudio/play-wave/allwrong.wav
Binary files differ
diff --git a/demos/modules/audio/play-wave/demo.mk b/demos/modules/gaudio/play-wave/demo.mk
index 242e57b5..cd6f941f 100644
--- a/demos/modules/audio/play-wave/demo.mk
+++ b/demos/modules/gaudio/play-wave/demo.mk
@@ -1,3 +1,3 @@
-DEMODIR = $(GFXLIB)/demos/modules/audio/play-wave
+DEMODIR = $(GFXLIB)/demos/modules/gaudio/play-wave
GFXINC += $(DEMODIR)
GFXSRC += $(DEMODIR)/main.c
diff --git a/demos/modules/audio/play-wave/gfxconf.h b/demos/modules/gaudio/play-wave/gfxconf.h
index 1480b919..a9bb6252 100644
--- a/demos/modules/audio/play-wave/gfxconf.h
+++ b/demos/modules/gaudio/play-wave/gfxconf.h
@@ -43,7 +43,7 @@
/* GFX sub-systems to turn on */
#define GFX_USE_GDISP TRUE
-#define GFX_USE_GAUDOUT TRUE
+#define GFX_USE_GAUDIO TRUE
#define GFX_USE_GFILE TRUE
/* Features for the GDISP sub-system. */
@@ -53,6 +53,9 @@
/* GDISP fonts to include */
#define GDISP_INCLUDE_FONT_UI2 TRUE
+/* Features for the GAUDIO sub-system */
+#define GAUDIO_NEED_PLAY TRUE
+
/* Features for the GFILE sub-system */
#define GFILE_NEED_ROMFS TRUE
diff --git a/demos/modules/audio/play-wave/main.c b/demos/modules/gaudio/play-wave/main.c
index e8cab254..f15ec7a1 100644
--- a/demos/modules/audio/play-wave/main.c
+++ b/demos/modules/gaudio/play-wave/main.c
@@ -34,8 +34,8 @@
#include "gfx.h"
/* Specify our timing parameters */
-#define MY_AUDIO_CHANNEL 0 /* Use channel 0 */
-#define MY_AUDIO_CHANNEL_IS_STEREO GAUDOUT_CHANNEL0_STEREO /* Is it stereo? */
+#define MY_AUDIO_CHANNEL 0 /* Use channel 0 */
+#define MY_AUDIO_CHANNEL_IS_STEREO GAUDOUT_CHANNEL0_IS_STEREO /* Is it stereo? */
// Storage for the wave header
static char whdr[32];
@@ -61,7 +61,9 @@ int main(void) {
// Any font will do
font = gdispOpenFont("*");
- // Allocate audio buffers - 4 x 512 byte buffers. You may need to increase this for slower cpu's.
+ // 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)) {
errmsg = "Err: No Memory";
goto theend;
@@ -179,8 +181,8 @@ int main(void) {
}
gfileClose(f);
- // Wait 3 seconds for the play to finish - FIX THIS
- gfxSleepMilliseconds(3000);
+ // Wait for the play to finish
+ gaudioPlayWait(TIME_INFINITE);
gdispDrawString(0, gdispGetHeight()/2+10, "Done", font, Green);
// The end
diff --git a/demos/modules/audio/play-wave/romfs_allwrong.h b/demos/modules/gaudio/play-wave/romfs_allwrong.h
index a374bde3..adc74fc7 100644
--- a/demos/modules/audio/play-wave/romfs_allwrong.h
+++ b/demos/modules/gaudio/play-wave/romfs_allwrong.h
@@ -1,7 +1,7 @@
/**
* This file was generated from "allwrong.wav" using...
*
- * file2c -bcs allwrong.wav romfs_allwrong.h
+ * file2c -dcs allwrong.wav romfs_allwrong.h
*
*/
static const char allwrong[] = {
diff --git a/demos/modules/audio/play-wave/romfs_files.h b/demos/modules/gaudio/play-wave/romfs_files.h
index db3e5491..db3e5491 100644
--- a/demos/modules/audio/play-wave/romfs_files.h
+++ b/demos/modules/gaudio/play-wave/romfs_files.h
diff --git a/drivers/audio/Win32/driver.mk b/drivers/audio/Win32/driver.mk
deleted file mode 100644
index 6f4ef084..00000000
--- a/drivers/audio/Win32/driver.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/audio/Win32/gaudin_lld.c \
- $(GFXLIB)/drivers/audio/Win32/gaudout_lld.c
-
-# Required include directories
-GFXINC += $(GFXLIB)/drivers/audio/Win32
diff --git a/drivers/audio/Win32/gaudin_lld.c b/drivers/audio/Win32/gaudin_lld.c
deleted file mode 100644
index 2c8431cf..00000000
--- a/drivers/audio/Win32/gaudin_lld.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file drivers/audio/Win32/gaudin_lld.c
- * @brief GAUDIN - Driver file for Win32.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GAUDIN
-
-/* Include the driver defines */
-#include "src/gaudin/driver.h"
-
-#undef Red
-#undef Green
-#undef Blue
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <stdio.h>
-#include <mmsystem.h>
-
-static HWAVEIN ah;
-static volatile int nQueuedBuffers;
-static bool_t isClosing;
-static WAVEHDR *pWaveHdrs;
-static HANDLE waveThread;
-static DWORD threadID;
-
-/*
-static void PrintWaveErrorMsg(DWORD err, TCHAR * str)
-{
- #define BUFFERSIZE 128
- char buffer[BUFFERSIZE];
-
- fprintf(stderr, "GAUDIN: ERROR 0x%08X: %s\r\n", err, str);
- if (mciGetErrorString(err, &buffer[0], sizeof(buffer)))
- fprintf(stderr, "%s\r\n", &buffer[0]);
- else
- fprintf(stderr, "0x%08X returned!\r\n", err);
-}
-*/
-
-/**************************** waveProc() *******************************
- * We don't use CALLBACK_FUNCTION because it is restricted to calling only
- * a few particular Windows functions, namely some of the time functions,
- * and a few of the Low Level MIDI API. If you violate this rule, your app can
- * hang inside of the callback). One of the Windows API that a callback can't
- * call is waveInAddBuffer() which is what we need to use whenever we receive a
- * MM_WIM_DATA. My callback would need to defer that job to another thread
- * anyway, so instead just use CALLBACK_THREAD here instead.
- *************************************************************************/
-
-static DWORD WINAPI waveProc(LPVOID arg) {
- MSG msg;
- (void) arg;
-
- while (GetMessage(&msg, 0, 0, 0)) {
- switch (msg.message) {
- case MM_WIM_DATA:
- GAUDIN_ISR_CompleteI((audin_sample_t *)((WAVEHDR *)msg.lParam)->lpData, ((WAVEHDR *)msg.lParam)->dwBytesRecorded/sizeof(audin_sample_t));
-
- /* Are we closing? */
- if (isClosing) {
- /* Yes. We aren't recording, so another WAVEHDR has been returned to us after recording has stopped.
- * When we get all of them back, things can be cleaned up
- */
- nQueuedBuffers--;
- waveInUnprepareHeader(ah, (WAVEHDR *)msg.lParam, sizeof(WAVEHDR));
- } else {
- /* No. Now we need to requeue this buffer so the driver can use it for another block of audio
- * data. NOTE: We shouldn't need to waveInPrepareHeader() a WAVEHDR that has already been prepared once.
- * Note: We are assuming here that both the application can still access the buffer while
- * it is on the queue.
- */
- waveInAddBuffer(ah, (WAVEHDR *)msg.lParam, sizeof(WAVEHDR));
- }
-
- break;
- }
- }
- return 0;
-}
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-void gaudin_lld_deinit(void) {
- if (ah) {
- isClosing = TRUE;
- waveInReset(ah);
- while(nQueuedBuffers) Sleep(1);
- waveInClose(ah);
- ah = 0;
- if (pWaveHdrs) gfxFree(pWaveHdrs);
- pWaveHdrs = 0;
- isClosing = FALSE;
- }
-}
-
-void gaudin_lld_init(const gaudin_params *paud) {
- WAVEFORMATEX wfx;
- size_t spaceleft;
- audin_sample_t *p;
- WAVEHDR *phdr;
- size_t nBuffers;
- size_t sz;
-
- if (!waveThread) {
- if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
- fprintf(stderr, "GAUDIN/GAUDOUT: Can't create WAVE recording thread\n");
- return;
- }
- CloseHandle(waveThread);
- }
-
- gaudin_lld_deinit();
-
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nChannels = paud->channel == GAUDIN_STEREO ? 2 : 1;
- wfx.nSamplesPerSec = paud->frequency;
- wfx.nBlockAlign = wfx.nChannels * sizeof(audin_sample_t);
- wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
- wfx.wBitsPerSample = sizeof(audin_sample_t) * 8;
- wfx.cbSize = 0;
-
- if (waveInOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, (DWORD_PTR)paud, CALLBACK_THREAD)) {
- fprintf(stderr, "GAUDIN: Can't open WAVE recording device\n");
- return;
- }
-
- /* We need to allocate a wave header for each buffer */
- nBuffers = (paud->bufcount + paud->samplesPerEvent - 1) / paud->samplesPerEvent;
- if (!(pWaveHdrs = gfxAlloc(nBuffers * sizeof(WAVEHDR)))) {
- fprintf(stderr, "GAUDIN: Buffer header allocation failed\n");
- return;
- }
-
- /* Prepare each buffer and send to the wavein device */
- spaceleft = paud->bufcount;
- for(p = paud->buffer, phdr = pWaveHdrs, spaceleft = paud->bufcount; spaceleft; p += sz, phdr++, spaceleft -= sz) {
- sz = spaceleft > paud->samplesPerEvent ? paud->samplesPerEvent : spaceleft;
- phdr->dwBufferLength = sz * sizeof(audin_sample_t);
- phdr->lpData = (LPSTR)p;
- phdr->dwFlags = 0;
- if (!waveInPrepareHeader(ah, phdr, sizeof(WAVEHDR))
- && !waveInAddBuffer(ah, phdr, sizeof(WAVEHDR)))
- nQueuedBuffers++;
- else
- fprintf(stderr, "GAUDIN: Buffer prepare failed\n");
- }
- if (!nQueuedBuffers)
- fprintf(stderr, "GAUDIN: Failed to prepare any buffers\n");
-}
-
-void gaudin_lld_start(void) {
- waveInStart(ah);
-}
-
-void gaudin_lld_stop(void) {
- waveInStop(ah);
-}
-
-#endif /* GFX_USE_GAUDIN */
diff --git a/drivers/audio/Win32/gaudin_lld_config.h b/drivers/audio/Win32/gaudin_lld_config.h
deleted file mode 100644
index 78ddffaa..00000000
--- a/drivers/audio/Win32/gaudin_lld_config.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file drivers/audio/Win32/gaudin_lld_config.h
- * @brief GAUDIN Driver config file.
- *
- * @addtogroup GAUDIN
- * @{
- */
-
-#ifndef GAUDIN_LLD_CONFIG_H
-#define GAUDIN_LLD_CONFIG_H
-
-#if GFX_USE_GAUDIN
-
-/*===========================================================================*/
-/* Driver hardware support. */
-/*===========================================================================*/
-
-/**
- * @brief The audio input sample type
- */
-//typedef uint8_t audin_sample_t;
-typedef int16_t audin_sample_t;
-
-/**
- * @brief The maximum sample frequency supported by this audio device
- */
-#define GAUDIN_MAX_SAMPLE_FREQUENCY 44100
-
-/**
- * @brief The number of bits in a sample
- */
-//#define GAUDIN_BITS_PER_SAMPLE 8
-#define GAUDIN_BITS_PER_SAMPLE 16
-
-/**
- * @brief The format of an audio sample
- */
-//#define GAUDIN_SAMPLE_FORMAT ARRAY_DATA_8BITUNSIGNED
-#define GAUDIN_SAMPLE_FORMAT ARRAY_DATA_16BITSIGNED
-
-/**
- * @brief The number of audio channels supported by this driver
- */
-#define GAUDIN_NUM_CHANNELS 2
-
-/**
- * @brief The list of audio channels and their uses
- * @{
- */
-#define GAUDIN_MONO 0
-#define GAUDIN_STEREO 1
-/** @} */
-
-#endif /* GFX_USE_GAUDIN */
-
-#endif /* GAUDIN_LLD_CONFIG_H */
-/** @} */
diff --git a/drivers/audio/Win32/readme.txt b/drivers/audio/Win32/readme.txt
deleted file mode 100644
index 784f0a89..00000000
--- a/drivers/audio/Win32/readme.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-This driver uses the Win32 audio system to provide GAUDIN and GAUDOUT channels.
-
-For GAUDIN - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
-For GAUDOUT - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
-
-For stereo, the samples are interleaved. Remember to allocate enough space for two samples per
-sample period.
-
-This is a simple driver that makes no changes to the mixer so set up the audio mixer using
-the windows control panel audio mixer before starting recording/playback.
diff --git a/drivers/audio/gadc/driver.mk b/drivers/audio/gadc/driver.mk
deleted file mode 100644
index b991ede8..00000000
--- a/drivers/audio/gadc/driver.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gaudin/gadc/gaudin_lld.c
-
-# Required include directories
-GFXINC += $(GFXLIB)/drivers/audio/gadc
diff --git a/drivers/gaudio/Win32/driver.mk b/drivers/gaudio/Win32/driver.mk
new file mode 100644
index 00000000..1ea338d5
--- /dev/null
+++ b/drivers/gaudio/Win32/driver.mk
@@ -0,0 +1,6 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gaudio/Win32/gaudio_record_lld.c \
+ $(GFXLIB)/drivers/gaudio/Win32/gaudio_play_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gaudio/Win32
diff --git a/drivers/audio/Win32/gaudout_lld_config.h b/drivers/gaudio/Win32/gaudio_play_config.h
index 907d44c6..4013e91f 100644
--- a/drivers/audio/Win32/gaudout_lld_config.h
+++ b/drivers/gaudio/Win32/gaudio_play_config.h
@@ -6,17 +6,17 @@
*/
/**
- * @file drivers/audio/Win32/gaudout_lld_config.h
- * @brief GAUDOUT Driver config file.
+ * @file drivers/gaudio/Win32/gaudio_play_config.h
+ * @brief GAUDIO Play Driver config file.
*
- * @addtogroup GAUDOUT
+ * @addtogroup GAUDIO
* @{
*/
-#ifndef GAUDOUT_LLD_CONFIG_H
-#define GAUDIN_LLD_CONFIG_H
+#ifndef GAUDIO_PLAY_CONFIG_H
+#define GAUDIO_PLAY_CONFIG_H
-#if GFX_USE_GAUDOUT
+#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY
/*===========================================================================*/
/* Driver hardware support. */
@@ -25,39 +25,39 @@
/**
* @brief The maximum sample frequency supported by this audio device
*/
-#define GAUDOUT_MAX_SAMPLE_FREQUENCY 44100
+#define GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY 44100
/**
* @brief The number of audio formats supported by this driver
*/
-#define GAUDOUT_NUM_FORMATS 2
+#define GAUDIO_PLAY_NUM_FORMATS 2
/**
* @brief The available audio sample formats in order of preference
*/
-#define GAUDOUT_FORMAT1 ARRAY_DATA_16BITSIGNED
-#define GAUDOUT_FORMAT2 ARRAY_DATA_8BITUNSIGNED
+#define GAUDIO_PLAY_FORMAT1 ARRAY_DATA_16BITSIGNED
+#define GAUDIO_PLAY_FORMAT2 ARRAY_DATA_8BITUNSIGNED
/**
* @brief The number of audio channels supported by this driver
*/
-#define GAUDOUT_NUM_CHANNELS 2
+#define GAUDIO_PLAY_NUM_CHANNELS 2
/**
* @brief Whether each channel is mono or stereo
*/
-#define GAUDOUT_CHANNEL0_STEREO FALSE
-#define GAUDOUT_CHANNEL1_STEREO TRUE
+#define GAUDIO_PLAY_CHANNEL0_IS_STEREO FALSE
+#define GAUDIO_PLAY_CHANNEL1_IS_STEREO TRUE
/**
* @brief The list of audio channel names and their uses
* @{
*/
-#define GAUDOUT_MONO 0
-#define GAUDOUT_STEREO 1
+#define GAUDIO_PLAY_MONO 0
+#define GAUDIO_PLAY_STEREO 1
/** @} */
-#endif /* GFX_USE_GAUDOUT */
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
-#endif /* GAUDOUT_LLD_CONFIG_H */
+#endif /* GAUDIO_PLAY_CONFIG_H */
/** @} */
diff --git a/drivers/audio/Win32/gaudout_lld.c b/drivers/gaudio/Win32/gaudio_play_lld.c
index 4fa6d605..6b4f2dab 100644
--- a/drivers/audio/Win32/gaudout_lld.c
+++ b/drivers/gaudio/Win32/gaudio_play_lld.c
@@ -6,16 +6,16 @@
*/
/**
- * @file drivers/audio/Win32/gaudout_lld.c
- * @brief GAUDOUT - Driver file for Win32.
+ * @file drivers/gaudio/Win32/gaudio_play_lld.c
+ * @brief GAUDIO - Play Driver file for Win32.
*/
#include "gfx.h"
-#if GFX_USE_GAUDOUT
+#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY
/* Include the driver defines */
-#include "src/gaudout/driver.h"
+#include "src/gaudio/driver_play.h"
#undef Red
#undef Green
@@ -36,20 +36,6 @@ static WAVEHDR WaveHdrs[MAX_WAVE_HEADERS];
static HANDLE waveThread;
static DWORD threadID;
-/*
-static void PrintWaveErrorMsg(DWORD err, TCHAR * str)
-{
- #define BUFFERSIZE 128
- char buffer[BUFFERSIZE];
-
- fprintf(stderr, "GAUDOUT: ERROR 0x%08X: %s\r\n", err, str);
- if (mciGetErrorString(err, &buffer[0], sizeof(buffer)))
- fprintf(stderr, "%s\r\n", &buffer[0]);
- else
- fprintf(stderr, "0x%08X returned!\r\n", err);
-}
-*/
-
/**************************** waveProc() *******************************
* We don't use CALLBACK_FUNCTION because it is restricted to calling only
* a few particular Windows functions, namely some of the time functions,
@@ -65,7 +51,9 @@ static bool_t senddata(WAVEHDR *pwh) {
// Get the next data block to send
gfxSystemLock();
- paud = gaudoutGetDataBlockI();
+ paud = gaudioPlayGetDataBlockI();
+ if (!paud && !nQueuedBuffers)
+ gaudioPlayDoneI();
gfxSystemUnlock();
if (!paud)
return FALSE;
@@ -77,13 +65,13 @@ static bool_t senddata(WAVEHDR *pwh) {
pwh->dwFlags = 0;
pwh->dwLoops = 0;
if (waveOutPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
- fprintf(stderr, "GAUDOUT: Failed to prepare a buffer");
+ fprintf(stderr, "GAUDIO: Failed to prepare a play buffer");
exit(-1);
}
// Send it to windows
if (waveOutWrite(ah, pwh, sizeof(WAVEHDR))) {
- fprintf(stderr, "GAUDOUT: Failed to write the buffer");
+ fprintf(stderr, "GAUDIO: Failed to write the play buffer");
exit(-1);
}
@@ -106,18 +94,25 @@ static DWORD WINAPI waveProc(LPVOID arg) {
// Give the buffer back to the Audio Free List
gfxSystemLock();
- gaudoutReleaseDataBlockI((GAudioData *)pwh->dwUser);
+ gaudioPlayReleaseDataBlockI((GAudioData *)pwh->dwUser);
gfxSystemUnlock();
pwh->lpData = 0;
nQueuedBuffers--;
- // Try and get a new block
- if ((!isRunning || !senddata(pwh)) && !nQueuedBuffers) {
- gfxSystemLock();
- gaudoutDoneI();
- gfxSystemUnlock();
+ // Are we stopping?
+ if (!isRunning) {
+ // Have we finished yet?
+ if (!nQueuedBuffers) {
+ gfxSystemLock();
+ gaudioPlayDoneI();
+ gfxSystemUnlock();
+ }
+ break;
}
- break;
+
+ // Try and get a new block
+ senddata(pwh);
+ break;
}
}
return 0;
@@ -127,17 +122,7 @@ static DWORD WINAPI waveProc(LPVOID arg) {
/* External declarations. */
/*===========================================================================*/
-void gaudout_lld_deinit() {
- if (ah) {
- isRunning = FALSE;
- waveOutReset(ah);
- while(nQueuedBuffers) Sleep(1);
- waveOutClose(ah);
- ah = 0;
- }
-}
-
-bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
+bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
WAVEFORMATEX wfx;
if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_16BITSIGNED)
@@ -145,40 +130,41 @@ bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat fo
if (!waveThread) {
if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
- fprintf(stderr, "GAUDOUT: Can't create WAVE play-back thread\n");
+ fprintf(stderr, "GAUDIO: Can't create WAVE play-back thread\n");
exit(-1);
}
CloseHandle(waveThread);
}
wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nChannels = channel == GAUDOUT_STEREO ? 2 : 1;
+ wfx.nChannels = channel == GAUDIO_PLAY_STEREO ? 2 : 1;
wfx.nSamplesPerSec = frequency;
wfx.nBlockAlign = wfx.nChannels * (format == ARRAY_DATA_8BITUNSIGNED ? 1 : 2);
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.wBitsPerSample = (format == ARRAY_DATA_8BITUNSIGNED ? 8 : 16);
wfx.cbSize = 0;
+ if (ah) {
+ waveOutClose(ah);
+ ah = 0;
+ }
if (waveOutOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
- fprintf(stderr, "GAUDOUT: Can't open WAVE play-back device\n");
+ fprintf(stderr, "GAUDIO: Can't open WAVE play-back device\n");
exit(-1);
}
return TRUE;
}
-bool_t gaudout_lld_set_volume(uint8_t vol) {
+bool_t gaudio_play_lld_set_volume(uint8_t vol) {
if (!ah)
return FALSE;
return waveOutSetVolume(ah, (((uint16_t)vol)<<8)|vol) != 0;
}
-void gaudout_lld_start(void) {
+void gaudio_play_lld_start(void) {
WAVEHDR *pwh;
- if (!ah)
- return;
-
isRunning = TRUE;
while (nQueuedBuffers < MAX_WAVE_HEADERS) {
// Find the empty one - there will always be at least one.
@@ -190,10 +176,10 @@ void gaudout_lld_start(void) {
}
}
-void gaudout_lld_stop(void) {
+void gaudio_play_lld_stop(void) {
isRunning = FALSE;
- if (ah)
- waveOutReset(ah);
+ waveOutReset(ah);
+ while(nQueuedBuffers) Sleep(1);
}
-#endif /* GFX_USE_GAUDOUT */
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
diff --git a/drivers/gaudio/Win32/gaudio_record_config.h b/drivers/gaudio/Win32/gaudio_record_config.h
new file mode 100644
index 00000000..4d952e1d
--- /dev/null
+++ b/drivers/gaudio/Win32/gaudio_record_config.h
@@ -0,0 +1,63 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file drivers/gaudio/Win32/gaudio_record_config.h
+ * @brief GAUDIO Record Driver config file.
+ *
+ * @addtogroup GAUDIO
+ * @{
+ */
+
+#ifndef GAUDIO_RECORD_CONFIG_H
+#define GAUDIO_RECORD_CONFIG_H
+
+#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+/**
+ * @brief The maximum sample frequency supported by this audio device
+ */
+#define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY 44100
+
+/**
+ * @brief The number of audio formats supported by this driver
+ */
+#define GAUDIO_RECORD_NUM_FORMATS 2
+
+/**
+ * @brief The available audio sample formats in order of preference
+ */
+#define GAUDIO_RECORD_FORMAT1 ARRAY_DATA_16BITSIGNED
+#define GAUDIO_RECORD_FORMAT2 ARRAY_DATA_8BITUNSIGNED
+
+/**
+ * @brief The number of audio channels supported by this driver
+ */
+#define GAUDIO_RECORD_NUM_CHANNELS 2
+
+/**
+ * @brief Whether each channel is mono or stereo
+ */
+#define GAUDIO_RECORD_CHANNEL0_IS_STEREO FALSE
+#define GAUDIO_RECORD_CHANNEL1_IS_STEREO TRUE
+
+/**
+ * @brief The list of audio channels and their uses
+ * @{
+ */
+#define GAUDIO_RECORD_MONO 0
+#define GAUDIO_RECORD_STEREO 1
+/** @} */
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
+
+#endif /* GAUDIO_RECORD_CONFIG_H */
+/** @} */
diff --git a/drivers/gaudio/Win32/gaudio_record_lld.c b/drivers/gaudio/Win32/gaudio_record_lld.c
new file mode 100644
index 00000000..259707e3
--- /dev/null
+++ b/drivers/gaudio/Win32/gaudio_record_lld.c
@@ -0,0 +1,187 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file drivers/gaudio/Win32/gaudio_record_lld.c
+ * @brief GAUDIO - Record Driver file for Win32.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
+
+/* Include the driver defines */
+#include "src/gaudio/driver_record.h"
+
+#undef Red
+#undef Green
+#undef Blue
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <stdio.h>
+#include <mmsystem.h>
+
+#define MAX_WAVE_HEADERS 2 // Larger numbers enable more buffering which is good for ensuring
+ // there are no skips due to data not being available, however larger
+ // numbers of buffers chews buffers on the free-list.
+
+static HWAVEIN ah = 0;
+static volatile int nQueuedBuffers;
+static bool_t isRunning;
+static WAVEHDR WaveHdrs[MAX_WAVE_HEADERS];
+static HANDLE waveThread;
+static DWORD threadID;
+
+/**************************** waveProc() *******************************
+ * We don't use CALLBACK_FUNCTION because it is restricted to calling only
+ * a few particular Windows functions, namely some of the time functions,
+ * and a few of the Low Level MIDI API. If you violate this rule, your app can
+ * hang inside of the callback). One of the Windows API that a callback can't
+ * call is waveInAddBuffer() which is what we need to use whenever we receive a
+ * MM_WIM_DATA. My callback would need to defer that job to another thread
+ * anyway, so instead just use CALLBACK_THREAD here instead.
+ *************************************************************************/
+
+static bool_t getbuffer(WAVEHDR *pwh) {
+ GAudioData *paud;
+
+ // Get the next data block to send
+ gfxSystemLock();
+ paud = gaudioRecordGetFreeBlockI();
+ if (!paud && !nQueuedBuffers)
+ gaudioRecordDoneI();
+ gfxSystemUnlock();
+ if (!paud)
+ return FALSE;
+
+ // Prepare the wave header for Windows
+ pwh->dwUser = (DWORD_PTR)paud;
+ pwh->lpData = (LPSTR)(paud+1); // The data is on the end of the structure
+ pwh->dwBufferLength = paud->size;
+ pwh->dwFlags = 0;
+ if (waveInPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
+ fprintf(stderr, "GAUDIO: Failed to prepare a record buffer");
+ exit(-1);
+ }
+
+ // Send it to windows
+ if (waveInAddBuffer(ah, pwh, sizeof(WAVEHDR))) {
+ fprintf(stderr, "GAUDIO: Failed to add the record buffer");
+ exit(-1);
+ }
+
+ nQueuedBuffers++;
+ return TRUE;
+}
+
+static DWORD WINAPI waveProc(LPVOID arg) {
+ MSG msg;
+ WAVEHDR *pwh;
+ GAudioData *paud;
+ (void) arg;
+
+ while (GetMessage(&msg, 0, 0, 0)) {
+ switch (msg.message) {
+ case MM_WIM_DATA:
+ pwh = (WAVEHDR *)msg.lParam;
+
+ // Windows - Let go!
+ waveInUnprepareHeader(ah, pwh, sizeof(WAVEHDR));
+
+ // Save the buffer in the audio record list
+ paud = (GAudioData *)pwh->dwUser;
+ paud->len = pwh->dwBytesRecorded;
+ gfxSystemLock();
+ gaudioRecordSaveDataBlockI(paud);
+ gfxSystemUnlock();
+ pwh->lpData = 0;
+ nQueuedBuffers--;
+
+ // Are we stopping?
+ if (!isRunning) {
+ // Have we finished yet?
+ if (!nQueuedBuffers) {
+ gfxSystemLock();
+ gaudioRecordDoneI();
+ gfxSystemUnlock();
+ }
+ break;
+ }
+
+ // Try and get a new block
+ getbuffer(pwh);
+ break;
+ }
+ }
+ return 0;
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+bool_t gaudio_record_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
+ WAVEFORMATEX wfx;
+
+ if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_16BITSIGNED)
+ return FALSE;
+
+ if (!waveThread) {
+ if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
+ fprintf(stderr, "GAUDIO: Can't create WAVE recording thread\n");
+ exit(-1);
+ }
+ CloseHandle(waveThread);
+ }
+
+ wfx.wFormatTag = WAVE_FORMAT_PCM;
+ wfx.nChannels = channel == GAUDIO_RECORD_STEREO ? 2 : 1;
+ wfx.nSamplesPerSec = frequency;
+ wfx.nBlockAlign = wfx.nChannels * (format == ARRAY_DATA_8BITUNSIGNED ? 1 : 2);
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+ wfx.wBitsPerSample = (format == ARRAY_DATA_8BITUNSIGNED ? 8 : 16);
+ wfx.cbSize = 0;
+
+ if (ah) {
+ waveInClose(ah);
+ ah = 0;
+ }
+ if (waveInOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
+ fprintf(stderr, "GAUDIN: Can't open WAVE recording device\n");
+ exit(-1);
+ }
+
+ return TRUE;
+}
+
+void gaudio_record_lld_start(void) {
+ WAVEHDR *pwh;
+
+ if (!ah)
+ return;
+
+ while (nQueuedBuffers < MAX_WAVE_HEADERS) {
+ // Find the empty one - there will always be at least one.
+ for(pwh = WaveHdrs; pwh->lpData; pwh++);
+
+ // Grab the next audio block from the free-list
+ if (!getbuffer(pwh))
+ break;
+ }
+ if (!isRunning) {
+ isRunning = TRUE;
+ waveInStart(ah);
+ }
+}
+
+void gaudio_record_lld_stop(void) {
+ isRunning = FALSE;
+ waveInReset(ah);
+ while(nQueuedBuffers) Sleep(1);
+}
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
diff --git a/drivers/gaudio/Win32/readme.txt b/drivers/gaudio/Win32/readme.txt
new file mode 100644
index 00000000..83cb9c33
--- /dev/null
+++ b/drivers/gaudio/Win32/readme.txt
@@ -0,0 +1,10 @@
+This driver uses the Win32 audio system to provide GAUDIO play and record channels.
+
+For PLAY - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
+For RECORD - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
+
+For stereo, the samples are interleaved. Remember to allocate enough space for two samples per
+sample period.
+
+This is a simple driver that makes no changes to the mixer so set up the audio mixer using
+the windows control panel audio mixer before starting recording/playback.
diff --git a/drivers/gaudio/gadc/driver.mk b/drivers/gaudio/gadc/driver.mk
new file mode 100644
index 00000000..4d79da25
--- /dev/null
+++ b/drivers/gaudio/gadc/driver.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gaudio/gadc/gaudio_record_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gaudio/gadc
diff --git a/drivers/audio/gadc/gaudin_lld_board_template.h b/drivers/gaudio/gadc/gaudio_record_board_template.h
index 89cc0c12..26e87d88 100644
--- a/drivers/audio/gadc/gaudin_lld_board_template.h
+++ b/drivers/gaudio/gadc/gaudio_record_board_template.h
@@ -6,15 +6,15 @@
*/
/**
- * @file drivers/gaudin/gadc/gaudin_lld_board_template.h
- * @brief GAUDIN Driver board config board file
+ * @file drivers/gaudio/gadc/gaudio_record_board_template.h
+ * @brief GAUDIO Record Driver board config board file
*
- * @addtogroup GAUDIN
+ * @addtogroup GAUDIO
* @{
*/
-#ifndef _GAUDIN_LLD_BOARD_H
-#define _GAUDIN_LLD_BOARD_H
+#ifndef _GAUDIO_RECORD_BOARD_H
+#define _GAUDIO_RECORD_BOARD_H
/*===========================================================================*/
/* Audio inputs on this board */
@@ -24,14 +24,14 @@
* @brief The number of audio channels supported by this driver
* @note This is an example
*/
-#define GAUDIN_NUM_CHANNELS 1
+#define GAUDIO_RECORD_NUM_CHANNELS 1
/**
* @brief The list of audio channels and their uses
* @note This is an example
* @{
*/
-#define GAUDIN_MICROPHONE 0
+#define GAUDIO_RECORD_MICROPHONE 0
/** @} */
/**
@@ -39,12 +39,12 @@
* @note This is an example
* @{
*/
-#ifdef GAUDIN_LLD_IMPLEMENTATION
- static uint32_t gaudin_lld_physdevs[GAUDIN_NUM_CHANNELS] = {
+#ifdef GAUDIO_RECORD_LLD_IMPLEMENTATION
+ static uint32_t gaudin_lld_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = {
GADC_PHYSDEV_MICROPHONE,
};
#endif
/** @} */
-#endif /* _GAUDIN_LLD_BOARD_H */
+#endif /* _GAUDIO_RECORD_BOARD_H */
/** @} */
diff --git a/drivers/audio/gadc/gaudin_lld_config.h b/drivers/gaudio/gadc/gaudio_record_config.h
index a9fd02ae..22d8750f 100644
--- a/drivers/audio/gadc/gaudin_lld_config.h
+++ b/drivers/gaudio/gadc/gaudio_record_config.h
@@ -6,54 +6,54 @@
*/
/**
- * @file drivers/gaudin/gadc/gaudin_lld_config.h
- * @brief GAUDIN Driver config file.
+ * @file drivers/gaudio/gadc/gaudio_record_config.h
+ * @brief GAUDIN Record Driver config file.
*
- * @addtogroup GAUDIN
+ * @addtogroup GAUDIO
* @{
*/
-#ifndef GAUDIN_LLD_CONFIG_H
-#define GAUDIN_LLD_CONFIG_H
+#ifndef GAUDIO_RECORD_CONFIG_H
+#define GAUDIO_RECORD_CONFIG_H
-#if GFX_USE_GAUDIN
+#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
/*===========================================================================*/
/* Driver hardware support. */
/*===========================================================================*/
/**
- * @brief The audio input sample type
+ * @brief The audio record sample type
* @details For this driver it matches the cpu sample type
*/
-typedef adcsample_t audin_sample_t;
+typedef adcsample_t audio_record_sample_t;
/**
* @brief The maximum sample frequency supported by this audio device
* @details For this driver it matches the GADC maximum high speed sample rate
*/
-#define GAUDIN_MAX_SAMPLE_FREQUENCY GADC_MAX_HIGH_SPEED_SAMPLERATE
+#define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY GADC_MAX_HIGH_SPEED_SAMPLERATE
/**
* @brief The number of bits in a sample
* @details For this driver it matches the cpu sample bits
*/
-#define GAUDIN_BITS_PER_SAMPLE GADC_BITS_PER_SAMPLE
+#define GAUDIO_RECORD_BITS_PER_SAMPLE GADC_BITS_PER_SAMPLE
/**
* @brief The format of an audio sample
* @details For this driver it matches the cpu sample format
*/
-#define GAUDIN_SAMPLE_FORMAT GADC_SAMPLE_FORMAT
+#define GAUDIO_RECORD_SAMPLE_FORMAT GADC_SAMPLE_FORMAT
/**
- * For the GAUDIN driver that uses GADC - all the remaining config definitions are specific
+ * For the GAUDIO driver that uses GADC - all the remaining config definitions are specific
* to the board.
*/
/* Include the user supplied board definitions */
-#include "gaudin_lld_board.h"
+#include "gaudio_record_board.h"
-#endif /* GFX_USE_GAUDIN */
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
-#endif /* GAUDIN_LLD_CONFIG_H */
+#endif /* GAUDIO_RECORD_CONFIG_H */
/** @} */
diff --git a/drivers/audio/gadc/gaudin_lld.c b/drivers/gaudio/gadc/gaudio_record_lld.c
index 002d9e9b..ee994dc1 100644
--- a/drivers/audio/gadc/gaudin_lld.c
+++ b/drivers/gaudio/gadc/gaudio_record_lld.c
@@ -6,10 +6,10 @@
*/
/**
- * @file drivers/gaudin/gadc/gaudin_lld.c
- * @brief GAUDIN - Driver file for using the cpu ADC (via GADC).
+ * @file drivers/gaudio/gadc/gaudio_record_lld.c
+ * @brief GAUDIO - Record Driver file for using the cpu ADC (via GADC).
*
- * @addtogroup GAUDIN
+ * @addtogroup GAUDIO
*
* @{
*/
@@ -18,20 +18,20 @@
* We are now implementing the driver - pull in our channel table
* from the board definitions.
*/
-#define GAUDIN_LLD_IMPLEMENTATION
+#define GAUDIO_RECORD_IMPLEMENTATION
#include "gfx.h"
-#if GFX_USE_GAUDIN
+#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
/* Double check the GADC system is turned on */
#if !GFX_USE_GADC
- #error "GAUDIN - The GADC driver for GAUDIN requires GFX_USE_GADC to be TRUE"
+ #error "GAUDIO - The GADC driver for GAUDIO requires GFX_USE_GADC to be TRUE"
#endif
/* Include the driver defines */
-#include "src/gaudin/driver.h"
+#include "src/gaudio/driver_record.h"
/*===========================================================================*/
/* External declarations. */
@@ -58,5 +58,5 @@ void gaudin_lld_stop(void) {
gadcHighSpeedStop();
}
-#endif /* GFX_USE_GAUDIN */
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
/** @} */
diff --git a/drivers/audio/gadc/readme.txt b/drivers/gaudio/gadc/readme.txt
index 1d3877e8..47d3f191 100644
--- a/drivers/audio/gadc/readme.txt
+++ b/drivers/gaudio/gadc/readme.txt
@@ -1,4 +1,4 @@
-This driver uses the generic GADC driver to provide a GAUDIN device.
+This driver uses the generic GADC driver to provide a GAUDIO recording device.
It supports whatever high speed device channels that your GADC driver and board supports.
diff --git a/gfx.h b/gfx.h
index 77aba969..de6047fc 100644
--- a/gfx.h
+++ b/gfx.h
@@ -62,7 +62,7 @@
* @brief GFX Graphics Display Basic API
* @details Defaults to FALSE
* @note Also add the specific hardware driver to your makefile.
- * Eg. include $(GFXLIB)/drivers/gdisp/Nokia6610/gdisp_lld.mk
+ * Eg. include $(GFXLIB)/drivers/gdisp/Nokia6610/driver.mk
*/
#ifndef GFX_USE_GDISP
#define GFX_USE_GDISP FALSE
@@ -106,9 +106,9 @@
* @details Defaults to FALSE
* @note Also add the specific hardware drivers to your makefile.
* Eg.
- * include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk
+ * include $(GFXLIB)/drivers/ginput/toggle/Pal/driver.mk
* and...
- * include $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld.mk
+ * include $(GFXLIB)/drivers/ginput/touch/MCU/driver.mk
*/
#ifndef GFX_USE_GINPUT
#define GFX_USE_GINPUT FALSE
@@ -121,24 +121,14 @@
#define GFX_USE_GADC FALSE
#endif
/**
- * @brief GFX Audio Input Device API
+ * @brief GFX Audio API
* @details Defaults to FALSE
* @note Also add the specific hardware drivers to your makefile.
* Eg.
- * include $(GFXLIB)/drivers/gaudin/GADC/gaudin_lld.mk
+ * include $(GFXLIB)/drivers/gaudio/GADC/driver.mk
*/
- #ifndef GFX_USE_GAUDIN
- #define GFX_USE_GAUDIN FALSE
- #endif
- /**
- * @brief GFX Audio Output Device API
- * @details Defaults to FALSE
- * @note Also add the specific hardware drivers to your makefile.
- * Eg.
- * include $(GFXLIB)/drivers/gaudout/PWM/gaudout_lld.mk
- */
- #ifndef GFX_USE_GAUDOUT
- #define GFX_USE_GAUDOUT FALSE
+ #ifndef GFX_USE_GAUDIO
+ #define GFX_USE_GAUDIO FALSE
#endif
/**
* @brief GFX Miscellaneous Routines API
@@ -173,8 +163,7 @@
#include "src/gwin/sys_options.h"
#include "src/ginput/sys_options.h"
#include "src/gadc/sys_options.h"
-#include "src/gaudin/sys_options.h"
-#include "src/gaudout/sys_options.h"
+#include "src/gaudio/sys_options.h"
/**
* Interdependency safety checks on the sub-systems.
@@ -187,8 +176,7 @@
#include "src/gwin/sys_rules.h"
#include "src/ginput/sys_rules.h"
#include "src/gdisp/sys_rules.h"
-#include "src/gaudout/sys_rules.h"
-#include "src/gaudin/sys_rules.h"
+#include "src/gaudio/sys_rules.h"
#include "src/gadc/sys_rules.h"
#include "src/gevent/sys_rules.h"
#include "src/gtimer/sys_rules.h"
@@ -210,8 +198,7 @@
#include "src/gwin/sys_defs.h"
#include "src/ginput/sys_defs.h"
#include "src/gadc/sys_defs.h"
-#include "src/gaudin/sys_defs.h"
-#include "src/gaudout/sys_defs.h"
+#include "src/gaudio/sys_defs.h"
#ifdef __cplusplus
extern "C" {
@@ -231,7 +218,7 @@ extern "C" {
/**
* @brief The one call to end it all
*
- * @note This will deinitialise each sub-system that has been turned on.
+ * @note This will de-initialise each sub-system that has been turned on.
*
* @api
*/
diff --git a/gfx.mk b/gfx.mk
index 8ac6e36b..8a2faa2b 100644
--- a/gfx.mk
+++ b/gfx.mk
@@ -9,7 +9,6 @@ include $(GFXLIB)/src/gtimer/sys_make.mk
include $(GFXLIB)/src/gwin/sys_make.mk
include $(GFXLIB)/src/ginput/sys_make.mk
include $(GFXLIB)/src/gadc/sys_make.mk
-include $(GFXLIB)/src/gaudin/sys_make.mk
-include $(GFXLIB)/src/gaudout/sys_make.mk
+include $(GFXLIB)/src/gaudio/sys_make.mk
include $(GFXLIB)/src/gmisc/sys_make.mk
include $(GFXLIB)/src/gfile/sys_make.mk
diff --git a/gfxconf.example.h b/gfxconf.example.h
index 79d932e8..99f5e569 100644
--- a/gfxconf.example.h
+++ b/gfxconf.example.h
@@ -218,15 +218,11 @@
///////////////////////////////////////////////////////////////////////////
-// GAUDIN //
+// GAUDIO //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GAUDIN FALSE
-
-
-///////////////////////////////////////////////////////////////////////////
-// GAUDOUT //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GAUDOUT FALSE
+#define GFX_USE_GAUDIO FALSE
+ #define GAUDIO_NEED_PLAY FALSE
+ #define GAUDIO_NEED_RECORD FALSE
///////////////////////////////////////////////////////////////////////////
@@ -243,4 +239,3 @@
#endif /* _GFXCONF_H */
-
diff --git a/src/gaudin/driver.h b/src/gaudin/driver.h
deleted file mode 100644
index b534e2a5..00000000
--- a/src/gaudin/driver.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file src/gaudin/driver.h
- * @brief GAUDIN - Audio Input driver header file.
- *
- * @defgroup Driver Driver
- * @ingroup GAUDIN
- * @{
- */
-
-#ifndef _GAUDIN_LLD_H
-#define _GAUDIN_LLD_H
-
-#include "gfx.h"
-
-#if GFX_USE_GAUDIN || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Type definitions */
-/*===========================================================================*/
-
-/**
- * @brief The structure passed to start a audio conversion
- * @note We use the structure instead of parameters purely to save
- * interrupt stack space which is very limited in some platforms.
- * @{
- */
-typedef struct gaudin_params_t {
- uint16_t channel;
- uint32_t frequency;
- audin_sample_t *buffer;
- size_t bufcount;
- size_t samplesPerEvent;
- } gaudin_params;
-/** @} */
-
-/**
- * @brief These routines are the callbacks that the driver uses.
- * @details Defined in the high level GAUDIN code.
- *
- * @iclass
- * @notapi
- *
- * @{
- */
-
-/**
- * @param[in] buffer The buffer
- * @param[in] n The amount of samples
- * */
-extern void GAUDIN_ISR_CompleteI(audin_sample_t *buffer, size_t n);
-
-extern void GAUDIN_ISR_ErrorI(void);
-/**
- * @}
- */
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Initialise the driver
- *
- * @param[in] paud Initialisation parameters
- *
- * @api
- */
-void gaudin_lld_init(const gaudin_params *paud);
-
-/**
- * @brief Start the audio input sampling
- *
- * @api
- */
-void gaudin_lld_start(void);
-
-/**
- * @brief Stop the audio input sampling
- *
- * @api
- */
-void gaudin_lld_stop(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GFX_USE_GADC */
-
-#endif /* _GADC_LLD_H */
-/** @} */
diff --git a/src/gaudin/gaudin.c b/src/gaudin/gaudin.c
deleted file mode 100644
index 2e3507ef..00000000
--- a/src/gaudin/gaudin.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file src/gaudin/gaudin.c
- * @brief GAUDIN sub-system code.
- *
- * @addtogroup GAUDIN
- * @{
- */
-#include "gfx.h"
-
-#if GFX_USE_GAUDIN
-
-/* Include the driver defines */
-#include "src/gaudin/driver.h"
-
-static gaudin_params aud;
-static gfxSem *paudSem;
-static GEventAudioIn *paudEvent;
-static audin_sample_t *lastbuffer;
-static size_t lastcount;
-static uint16_t audFlags;
- #define AUDFLG_RUNNING 0x0001
- #define AUDFLG_USE_EVENTS 0x0002
-
-#if GFX_USE_GEVENT
- static GTimer AudGTimer;
-
- static void AudGTimerCallback(void *param) {
- (void) param;
- GSourceListener *psl;
- GEventADC *pe;
-
- psl = 0;
- while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
- if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) {
- // This listener is missing - save this.
- psl->srcflags |= GAUDIN_LOSTEVENT;
- continue;
- }
-
- pe->type = GEVENT_AUDIO_IN;
- pe->channel = aud.channel;
- pe->count = lastcount;
- pe->buffer = lastbuffer;
- pe->flags = psl->srcflags;
- psl->srcflags = 0;
- geventSendEvent(psl);
- }
- }
-#endif
-
-void GAUDIN_ISR_CompleteI(audin_sample_t *buffer, size_t n) {
- /* Save the details */
- lastcount = n;
- lastbuffer = buffer;
-
- /* Signal the user with the data */
- if (paudEvent) {
- #if GFX_USE_GEVENT
- paudEvent->type = GEVENT_AUDIO_IN;
- #endif
- paudEvent->channel = aud.channel;
- paudEvent->count = lastcount;
- paudEvent->buffer = lastbuffer;
- paudEvent->flags = 0;
- }
-
- /* Our two signalling mechanisms */
- if (paudSem)
- gfxSemSignalI(paudSem);
-
- #if GFX_USE_GEVENT
- if (audFlags & AUDFLG_USE_EVENTS)
- gtimerJabI(&AudGTimer);
- #endif
-}
-
-void GAUDIN_ISR_ErrorI(void) {
- /* Ignore any errors for now */
-}
-
-void _gaudinInit(void)
-{
- #if GFX_USE_GEVENT
- gtimerInit(&AudGTimer);
- #endif
-}
-
-void _gaudinDeinit(void)
-{
- // Commented stuff still ToDo
- #if GFX_USE_GEVENT
- gtimerDeinit(&AudGTimer);
- #endif
-}
-
-bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer, size_t bufcount, size_t samplesPerEvent) {
- /* Check the channel is valid */
- if (channel >= GAUDIN_NUM_CHANNELS || frequency > GAUDIN_MAX_SAMPLE_FREQUENCY)
- return FALSE;
-
- /* Stop any existing transfers */
- if ((audFlags & AUDFLG_RUNNING))
- gaudin_lld_stop();
- audFlags = 0;
-
- /* Initialise everything */
- aud.channel = channel;
- aud.frequency = frequency;
- aud.buffer = buffer;
- aud.bufcount = bufcount;
- aud.samplesPerEvent = samplesPerEvent;
- paudSem = 0;
- paudEvent = 0;
-
- /* Set up the low level driver */
- gaudin_lld_init(&aud);
- return TRUE;
-}
-
-#if GFX_USE_GEVENT
- GSourceHandle gaudinGetSource(void) {
- if (!gtimerIsActive(&AudGTimer))
- gtimerStart(&AudGTimer, AudGTimerCallback, 0, TRUE, TIME_INFINITE);
- audFlags |= AUDFLG_USE_EVENTS;
- return (GSourceHandle)&aud;
- }
-#endif
-
-void gaudinSetBSem(gfxSem *pbsem, GEventAudioIn *pEvent) {
- gfxSystemLock();
- paudSem = pbsem;
- paudEvent = pEvent;
- gfxSystemUnlock();
-}
-
-void gaudinStart(void) {
- if (!(audFlags & AUDFLG_RUNNING)) {
- audFlags |= AUDFLG_RUNNING;
- gaudin_lld_start();
- }
-}
-
-void gaudinStop(void) {
- if ((audFlags & AUDFLG_RUNNING)) {
- gaudin_lld_stop();
- audFlags &= ~AUDFLG_RUNNING;
- }
-}
-
-#endif /* GFX_USE_GAUDIN */
-/** @} */
diff --git a/src/gaudin/sys_defs.h b/src/gaudin/sys_defs.h
deleted file mode 100644
index c65a69c1..00000000
--- a/src/gaudin/sys_defs.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file src/gaudin/sys_defs.h
- *
- * @addtogroup GAUDIN
- *
- * @brief Module to read audio inputs
- *
- * @{
- */
-
-#ifndef _GAUDIN_H
-#define _GAUDIN_H
-
-#include "gfx.h"
-
-#if GFX_USE_GAUDIN || defined(__DOXYGEN__)
-
-/* Include the driver defines */
-#include "gaudin_lld_config.h"
-
-/*===========================================================================*/
-/* Type definitions */
-/*===========================================================================*/
-
-// Event types for GAUDIN
-#define GEVENT_AUDIO_IN (GEVENT_GAUDIN_FIRST+0)
-
-/**
- * @brief The Audio Input event structure.
- * @{
- */
-typedef struct GEventAudioIn_t {
- #if GFX_USE_GEVENT || defined(__DOXYGEN__)
- /**
- * @brief The type of this event (GEVENT_AUDIO_IN)
- */
- GEventType type;
- #endif
- /**
- * @brief The current channel
- */
- uint16_t channel;
- /**
- * @brief The event flags
- */
- uint16_t flags;
- /**
- * @brief The event flag values.
- * @{
- */
- #define GAUDIN_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */
- /** @} */
- /**
- * @brief The number of audio samples in the buffer
- */
- size_t count;
- /**
- * @brief The buffer containing the audio samples
- */
- audin_sample_t *buffer;
-} GEventAudioIn;
-/** @} */
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Initialise (but not start) the Audio Input Subsystem.
- * @details Returns FALSE for an invalid channel or other invalid parameter.
- *
- * @param[in] channel The channel to convert. Can be set from 0 to GAUDIN_NUM_CHANNELS - 1.
- * @param[in] frequency The sample frequency
- * @param[in] buffer The static buffer to put the samples into.
- * @param[in] bufcount The total number of conversions that will fit in the buffer.
- * @param[in] samplesPerEvent The number of conversions to do before returning an event.
- *
- * @note Only one channel is active at a time. If an audio input is running it will be stopped.
- * The Event subsystem is disconnected from the audio subsystem and any binary semaphore
- * event is forgotten.
- * @note Some channels may be stereo channels which return twice as much sample data with
- * the left and right channel data interleaved. Other channels may be mono channels.
- * Where stereo channels exist it would be common for the low level driver to also
- * offer the left and right channels separately.
- * @note Due to a bug in Chibi-OS countPerEvent must be even if using the GADC low level audio driver.
- * If bufcount is not evenly divisable by countPerEvent, the remainder must also be even.
- * This requirement may not apply to other GAUDIN drivers.
- * @note The number of samples for stereo devices will be double the number of conversions.
- * Make sure you allocate your buffers large enough. Each channel is then interleaved
- * into the provided buffer. Note 'bufcount' and 'countPerEvent' parameters describe the
- * number of conversions not the number of samples.
- * @note The buffer is circular. When the end of the buffer is reached it will start
- * putting data into the beginning of the buffer again.
- * @note The event listener must process the event (and the data in it) before the
- * next event occurs. If not, the following event will be lost.
- * @note If bufcount is evenly divisable by countPerEvent, then every event will return
- * countPerEvent conversions. If bufcount is not evenly divisable, it will return
- * a block of samples containing less than countPerEvent samples when it reaches the
- * end of the buffer.
- *
- * @return FALSE if invalid channel or parameter
- *
- * @api
- */
-bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer, size_t bufcount, size_t samplesPerEvent);
-
-#if GFX_USE_GEVENT || defined(__DOXYGEN__)
- /**
- * @brief Turn on sending results to the GEVENT sub-system.
- * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_IN events.
- *
- * @note The audio input will not use the GEVENT system unless this is
- * called first. This saves processing time if the application does
- * not want to use the GEVENT sub-system for audio input.
- * Once turned on it can only be turned off by calling @p gaudinInit() again.
- * @note The audio input is capable of signalling via this method and a binary semaphore
- * at the same time.
- *
- * @return The GSourceHandle
- *
- * @api
- */
- GSourceHandle gaudinGetSource(void);
-#endif
-
-/**
- * @brief Allow retrieving of results from the audio input using a Binary Semaphore and a static event buffer.
- *
- * @param[in] pbsem The semaphore is signaled when data is available.
- * @param[in] pEvent The static event buffer to place the result information.
- *
- * @note Passing a NULL for pbsem or pEvent will turn off signalling via this method.
- * @note The audio input is capable of signalling via this method and the GEVENT
- * sub-system at the same time.
- *
- * @api
- */
-void gaudinSetBSem(gfxSem *pbsem, GEventAudioIn *pEvent);
-
-/**
- * @brief Start the audio input conversions.
- * @pre It must have been initialised first with @p gaudinInit()
- *
- * @api
- */
-void gaudinStart(void);
-
-/**
- * @brief Stop the audio input conversions.
- *
- * @api
- */
-void gaudinStop(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GFX_USE_GAUDIN */
-
-#endif /* _GAUDIN_H */
-/** @} */
-
diff --git a/src/gaudin/sys_make.mk b/src/gaudin/sys_make.mk
deleted file mode 100644
index 16bb33b7..00000000
--- a/src/gaudin/sys_make.mk
+++ /dev/null
@@ -1 +0,0 @@
-GFXSRC += $(GFXLIB)/src/gaudin/gaudin.c
diff --git a/src/gaudin/sys_options.h b/src/gaudin/sys_options.h
deleted file mode 100644
index 305a6f8d..00000000
--- a/src/gaudin/sys_options.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file src/gaudin/sys_options.h
- * @brief GAUDIN - Audio Input subsystem options header file.
- *
- * @addtogroup GAUDIN
- * @{
- */
-
-#ifndef _GAUDIN_OPTIONS_H
-#define _GAUDIN_OPTIONS_H
-
-/**
- * @name GAUDIN Functionality to be included
- * @{
- */
-/**
- * @}
- *
- * @name GAUDIN Optional Sizing Parameters
- * @{
- */
-/** @} */
-
-#endif /* _GAUDIN_OPTIONS_H */
-/** @} */
diff --git a/src/gaudin/sys_rules.h b/src/gaudin/sys_rules.h
deleted file mode 100644
index 21d2552f..00000000
--- a/src/gaudin/sys_rules.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file src/gaudin/sys_rules.h
- * @brief GAUDIN safety rules header file.
- *
- * @addtogroup GAUDIN
- * @{
- */
-
-#ifndef _GAUDIN_RULES_H
-#define _GAUDIN_RULES_H
-
-#if GFX_USE_GAUDIN
- #if GFX_USE_GEVENT && !GFX_USE_GTIMER
- #if GFX_DISPLAY_RULE_WARNINGS
- #warning "GAUDIN: GFX_USE_GTIMER is required if GFX_USE_GAUDIN and GFX_USE_GEVENT are TRUE. It has been turned on for you."
- #endif
- #undef GFX_USE_GTIMER
- #define GFX_USE_GTIMER TRUE
- #endif
-#endif
-
-#endif /* _GAUDIN_RULES_H */
-/** @} */
diff --git a/src/gaudout/driver.h b/src/gaudio/driver_play.h
index bd00d06d..72ad4747 100644
--- a/src/gaudout/driver.h
+++ b/src/gaudio/driver_play.h
@@ -6,20 +6,20 @@
*/
/**
- * @file src/gaudout/driver.h
- * @brief GAUDOUT - Audio Output driver header file.
+ * @file src/gaudio/driver_play.h
+ * @brief GAUDIO - Audio play driver header file.
*
* @defgroup Driver Driver
- * @ingroup GAUDOUT
+ * @ingroup GAUDIO
* @{
*/
-#ifndef _GAUDOUT_LLD_H
-#define _GAUDOUT_LLD_H
+#ifndef _GAUDIO_PLAY_LLD_H
+#define _GAUDIO_PLAY_LLD_H
#include "gfx.h"
-#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
+#if (GFX_USE_GAUDIO && GAUDIO_NEED_PLAY) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Type definitions */
@@ -37,38 +37,38 @@ extern "C" {
* @brief Get a block of audio data to play
* @return A pointer to the GAaudioData structure or NULL if none is currently available
*
- * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers.
+ * @note Defined in the high level GAUDIO code for use by the GAUDIO play drivers.
*
* @iclass
* @notapi
*/
-GAudioData *gaudoutGetDataBlockI(void);
+GAudioData *gaudioPlayGetDataBlockI(void);
/**
- * @brief Release a block of audio data after playing
+ * @brief Release a block of audio data to the free list
*
* @param[in] paud The GAudioData block to be released.
*
- * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers.
+ * @note Defined in the high level GAUDIO code for use by the GAUDIO play drivers.
*
* @iclass
* @notapi
*/
-void gaudoutReleaseDataBlockI(GAudioData *paud);
+void gaudioPlayReleaseDataBlockI(GAudioData *paud);
/**
* @brief Signal that all playing has now stopped
*
- * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers.
+ * @note Defined in the high level GAUDIO code for use by the GAUDIO play drivers.
*
* @iclass
* @notapi
*/
-void gaudoutDoneI(void);
+void gaudioPlayDoneI(void);
/**
- * @brief Initialise the driver
- * @return TRUE if the channel and frequency are valid.
+ * @brief Initialise the play driver
+ * @return TRUE if the channel, frequency and format are valid.
*
* @param[in] channel The channel to use (see the driver for the available channels provided)
* @param[in] frequency The sample frequency to use
@@ -78,38 +78,30 @@ void gaudoutDoneI(void);
*
* @api
*/
-bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
-
-/**
- * @brief De-Initialise the driver
- *
- * @note The audio output will always have been stopped first by the high level layer.
- * @note This may be called before a @p gaudout_lld_init() has occurred.
- *
- * @api
- */
-void gaudout_lld_deinit(void);
+bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
/**
* @brief Start the audio output playing
*
* @note This may be called at any stage including while the driver
* is already playing. The driver should check for data blocks
- * to play using @p gaudoutGetDataBlockI().
+ * to play using @p gaudioPlayGetDataBlockI().
*
* @api
*/
-void gaudout_lld_start(void);
+void gaudio_play_lld_start(void);
/**
* @brief Stop the audio output playing.
*
* @note Some drivers may only stop playing at a data block boundary.
- * @note This may be called before a @p gaudout_lld_init() has occurred.
+ * @note It is possible but unlikely for it to be called when playing has already stopped.
+ * @note It should not return until all active buffers (currently in use by the driver)
+ * have been returned to the free-list and @p gaudioPlayDoneI() has been called.
*
* @api
*/
-void gaudout_lld_stop(void);
+void gaudio_play_lld_stop(void);
/**
* @brief Set the output volume.
@@ -122,13 +114,13 @@ void gaudout_lld_stop(void);
*
* @api
*/
-bool_t gaudout_lld_set_volume(uint8_t vol);
+bool_t gaudio_play_lld_set_volume(uint8_t vol);
#ifdef __cplusplus
}
#endif
-#endif /* GFX_USE_GAUDOUT */
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
-#endif /* _GAUDOUT_LLD_H */
+#endif /* _GAUDIO_PLAY_LLD_H */
/** @} */
diff --git a/src/gaudio/driver_record.h b/src/gaudio/driver_record.h
new file mode 100644
index 00000000..252cae5c
--- /dev/null
+++ b/src/gaudio/driver_record.h
@@ -0,0 +1,108 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gaudio/driver_record.h
+ * @brief GAUDIO - Audio Recording driver header file.
+ *
+ * @defgroup Driver Driver
+ * @ingroup GAUDIO
+ * @{
+ */
+
+#ifndef _GAUDIO_RECORD_LLD_H
+#define _GAUDIO_RECORD_LLD_H
+
+#include "gfx.h"
+
+#if (GFX_USE_GAUDIO && GAUDIO_NEED_RECORD) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+/**
+ * @brief Get a free block of audio data that we can record into
+ * @return A pointer to the GAaudioData structure or NULL if none is currently available
+ *
+ * @note Defined in the high level GAUDIO code for use by the GAUDIO record drivers.
+ *
+ * @iclass
+ * @notapi
+ */
+GAudioData *gaudioRecordGetFreeBlockI(void);
+
+/**
+ * @brief Save a block of recorded audio data ready for the application
+ *
+ * @param[in] paud The GAudioData block with data.
+ *
+ * @note Defined in the high level GAUDIO code for use by the GAUDIO record drivers.
+ *
+ * @iclass
+ * @notapi
+ */
+void gaudioRecordSaveDataBlockI(GAudioData *paud);
+
+/**
+ * @brief Signal that all recording has now stopped
+ *
+ * @note Defined in the high level GAUDIO code for use by the GAUDIO record drivers.
+ *
+ * @iclass
+ * @notapi
+ */
+void gaudioRecordDoneI(void);
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialise the record driver
+ * @return TRUE if the channel, frequency and format are valid.
+ *
+ * @param[in] channel The channel to use (see the driver for the available channels provided)
+ * @param[in] frequency The sample frequency to use
+ * @param[in] format The sample format
+ *
+ * @note The driver will always have been stopped and de-init before this is called.
+ *
+ * @api
+ */
+bool_t gaudio_record_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
+
+/**
+ * @brief Start the audio recording
+ *
+ * @api
+ */
+void gaudio_record_lld_start(void);
+
+/**
+ * @brief Stop the audio recording.
+ *
+ * @note Some drivers may only stop recording at a data block boundary.
+ * @note This routine should not return until any currently active buffers have been
+ * saved (even if with zero length) and @p gaudioRecordDoneI() has been called.
+ *
+ * @api
+ */
+void gaudio_record_lld_stop(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
+
+#endif /* _GAUDIO_RECORD_LLD_H */
+/** @} */
diff --git a/src/gaudio/gaudio.c b/src/gaudio/gaudio.c
new file mode 100644
index 00000000..a83dcd85
--- /dev/null
+++ b/src/gaudio/gaudio.c
@@ -0,0 +1,318 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gaudio/gaudio.c
+ * @brief GAUDIO sub-system code.
+ *
+ * @addtogroup GAUDIO
+ * @{
+ */
+#include "gfx.h"
+
+#if GFX_USE_GAUDIO
+
+static gfxQueueGSync freeList;
+
+#if GAUDIO_NEED_PLAY
+ #include "src/gaudio/driver_play.h"
+
+ static gfxQueueASync playList;
+ static gfxSem playComplete;
+ static uint16_t playFlags;
+ #define PLAYFLG_USEEVENTS 0x0001
+ #define PLAYFLG_PLAYING 0x0002
+ #define PLAYFLG_ISINIT 0x0004
+ #if GFX_USE_GEVENT
+ static GTimer playTimer;
+ static void PlayTimerCallback(void *param);
+ #endif
+#endif
+
+#if GAUDIO_NEED_RECORD
+ #include "src/gaudio/driver_record.h"
+
+ static gfxQueueGSync recordList;
+ static uint16_t recordFlags;
+ #define RECORDFLG_USEEVENTS 0x0001
+ #define RECORDFLG_RECORDING 0x0002
+ #define RECORDFLG_STALLED 0x0004
+ #define RECORDFLG_ISINIT 0x0008
+ #if GFX_USE_GEVENT
+ static GTimer recordTimer;
+ static void RecordTimerCallback(void *param);
+ #endif
+#endif
+
+
+void _gaudioInit(void)
+{
+ gfxQueueGSyncInit(&freeList);
+ #if GAUDIO_NEED_PLAY
+ gfxQueueASyncInit(&playList);
+ #if GFX_USE_GEVENT
+ gtimerInit(&playTimer);
+ #endif
+ gfxSemInit(&playComplete, 0, 0);
+ #endif
+ #if GAUDIO_NEED_RECORD
+ gfxQueueGSyncInit(&recordList);
+ #if GFX_USE_GEVENT
+ gtimerInit(&recordTimer);
+ #endif
+ #endif
+}
+
+void _gaudioDeinit(void)
+{
+ #if GAUDIO_NEED_PLAY
+ #if GFX_USE_GEVENT
+ gtimerDeinit(&playTimer);
+ #endif
+ gfxSemDestroy(&playComplete);
+ #endif
+ #if GAUDIO_NEED_RECORD
+ #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) {
+ gaudioPlayStop();
+ playFlags &= ~PLAYFLG_ISINIT;
+ if (!gaudio_play_lld_init(channel, frequency, format))
+ return FALSE;
+ playFlags |= PLAYFLG_ISINIT;
+ return TRUE;
+ }
+
+ void gaudioPlay(GAudioData *paud) {
+ if (!(playFlags & PLAYFLG_ISINIT)) {
+ // Oops - init failed - return it directly to the free-list
+ if (paud) {
+ gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud);
+ gfxYield(); // Make sure we get no endless cpu hogging loops
+ }
+ return;
+ }
+
+ if (paud)
+ gfxQueueASyncPut(&playList, (gfxQueueASyncItem *)paud);
+ playFlags |= PLAYFLG_PLAYING;
+ gaudio_play_lld_start();
+ }
+
+ void gaudioPlayPause(void) {
+ if ((playFlags & (PLAYFLG_ISINIT|PLAYFLG_PLAYING)) == (PLAYFLG_ISINIT|PLAYFLG_PLAYING))
+ gaudio_play_lld_stop();
+ }
+
+ void gaudioPlayStop(void) {
+ GAudioData *paud;
+
+ if (playFlags & PLAYFLG_PLAYING)
+ gaudio_play_lld_stop();
+ while((paud = (GAudioData *)gfxQueueASyncGet(&playList)))
+ gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud);
+ }
+
+ bool_t gaudioPlaySetVolume(uint8_t vol) {
+ return gaudio_play_lld_set_volume(vol);
+ }
+
+ bool_t gaudioPlayWait(delaytime_t ms) {
+ if (!(playFlags & PLAYFLG_PLAYING))
+ return TRUE;
+ return gfxSemWait(&playComplete, ms);
+ }
+
+ #if GFX_USE_GEVENT
+ static void PlayTimerCallback(void *param) {
+ (void) param;
+ GSourceListener *psl;
+ GEventAudioPlay *pe;
+
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)&playTimer, psl))) {
+ if (!(pe = (GEventAudioPlay *)geventGetEventBuffer(psl))) {
+ // This listener is missing - save this.
+ psl->srcflags |= GAUDIO_PLAY_LOSTEVENT;
+ continue;
+ }
+
+ pe->type = GEVENT_AUDIO_PLAY;
+ pe->flags = psl->srcflags;
+ psl->srcflags = 0;
+ if ((playFlags & PLAYFLG_PLAYING))
+ pe->flags |= GAUDIO_PLAY_PLAYING;
+ if (!gfxQueueGSyncIsEmpty(&freeList))
+ pe->flags |= GAUDIO_PLAY_FREEBLOCK;
+ geventSendEvent(psl);
+ }
+ }
+
+ GSourceHandle gaudioPlayGetSource(void) {
+ if (!gtimerIsActive(&playTimer))
+ gtimerStart(&playTimer, PlayTimerCallback, 0, TRUE, TIME_INFINITE);
+ playFlags |= PLAYFLG_USEEVENTS;
+ return (GSourceHandle)&playTimer;
+ }
+ #endif
+
+ /**
+ * Routines provided for use by drivers.
+ */
+
+ GAudioData *gaudioPlayGetDataBlockI(void) {
+ return (GAudioData *)gfxQueueASyncGetI(&playList);
+ }
+
+ void gaudioPlayReleaseDataBlockI(GAudioData *paud) {
+ gfxQueueGSyncPutI(&freeList, (gfxQueueGSyncItem *)paud);
+ #if GFX_USE_GEVENT
+ if (playFlags & PLAYFLG_USEEVENTS)
+ gtimerJabI(&playTimer);
+ #endif
+ }
+
+ void gaudioPlayDoneI(void) {
+ playFlags &= ~PLAYFLG_PLAYING;
+ #if GFX_USE_GEVENT
+ if (playFlags & PLAYFLG_USEEVENTS)
+ gtimerJabI(&playTimer);
+ #endif
+ gfxSemSignalI(&playComplete); // This should really be gfxSemSignalAllI(&playComplete);
+ }
+#endif
+
+#if GAUDIO_NEED_RECORD
+ bool_t gaudioRecordInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
+ gaudioRecordStop();
+ recordFlags &= ~RECORDFLG_ISINIT;
+ if (!gaudio_record_lld_init(channel, frequency, format))
+ return FALSE;
+ recordFlags |= RECORDFLG_ISINIT;
+ return TRUE;
+ }
+
+ void gaudioRecordStart(void) {
+ if (!(recordFlags & RECORDFLG_ISINIT))
+ return; // Oops - init failed
+
+ recordFlags |= RECORDFLG_RECORDING;
+ recordFlags &= ~RECORDFLG_STALLED;
+ gaudio_record_lld_start();
+ }
+
+ void gaudioRecordStop(void) {
+ GAudioData *paud;
+
+ 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);
+ }
+
+ GAudioData *gaudioRecordGetData(delaytime_t ms) {
+ return (GAudioData *)gfxQueueGSyncGet(&recordList, ms);
+ }
+
+ #if GFX_USE_GEVENT
+ static void RecordTimerCallback(void *param) {
+ (void) param;
+ GSourceListener *psl;
+ GEventAudioRecord *pe;
+
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)&recordTimer, psl))) {
+ if (!(pe = (GEventAudioRecord *)geventGetEventBuffer(psl))) {
+ // This listener is missing - save this.
+ psl->srcflags |= GAUDIO_RECORD_LOSTEVENT;
+ continue;
+ }
+ pe->type = GEVENT_AUDIO_RECORD;
+ pe->flags = psl->srcflags;
+ psl->srcflags = 0;
+ if ((recordFlags & RECORDFLG_RECORDING))
+ pe->flags |= GAUDIO_RECORD_RECORDING;
+ if ((recordFlags & RECORDFLG_STALLED))
+ pe->flags |= GAUDIO_RECORD_STALL;
+ if (!gfxQueueGSyncIsEmpty(&recordList))
+ pe->flags |= GAUDIO_RECORD_GOTBLOCK;
+ geventSendEvent(psl);
+ }
+ }
+
+ GSourceHandle gaudioRecordGetSource(void) {
+ if (!gtimerIsActive(&recordTimer))
+ gtimerStart(&recordTimer, RecordTimerCallback, 0, TRUE, TIME_INFINITE);
+ recordFlags |= RECORDFLG_USEEVENTS;
+ return (GSourceHandle)&recordTimer;
+ }
+ #endif
+
+ /**
+ * Routines provided for use by drivers.
+ */
+
+ GAudioData *gaudioRecordGetFreeBlockI(void) {
+ return (GAudioData *)gfxQueueGSyncGetI(&freeList);
+ }
+
+ void gaudioRecordSaveDataBlockI(GAudioData *paud) {
+ gfxQueueGSyncPutI(&recordList, (gfxQueueGSyncItem *)paud);
+ #if GFX_USE_GEVENT
+ if (recordFlags & RECORDFLG_USEEVENTS)
+ gtimerJabI(&recordTimer);
+ #endif
+ }
+
+ void gaudioRecordDoneI(void) {
+ recordFlags |= RECORDFLG_STALLED;
+ #if GFX_USE_GEVENT
+ if (recordFlags & RECORDFLG_USEEVENTS)
+ gtimerJabI(&recordTimer);
+ #endif
+ }
+#endif
+
+#endif /* GFX_USE_GAUDIO */
+/** @} */
diff --git a/src/gaudio/sys_defs.h b/src/gaudio/sys_defs.h
new file mode 100644
index 00000000..a9a951b7
--- /dev/null
+++ b/src/gaudio/sys_defs.h
@@ -0,0 +1,340 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gaudio/sys_defs.h
+ *
+ * @addtogroup GAUDIO
+ *
+ * @brief Module to handle audio recording and play-back
+ *
+ * @{
+ */
+
+#ifndef _GAUDIO_H
+#define _GAUDIO_H
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDIO || defined(__DOXYGEN__)
+
+/* Include the driver defines */
+#if GAUDIO_NEED_PLAY
+ #include "gaudio_play_config.h"
+#endif
+#if GAUDIO_NEED_RECORD
+ #include "gaudio_record_config.h"
+#endif
+
+/*===========================================================================*/
+/* 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)
+
+#if GFX_USE_GEVENT || defined(__DOXYGEN__)
+ /**
+ * @brief The Audio play event structure.
+ * @{
+ */
+ typedef struct GEventAudioPlay_t {
+ /**
+ * @brief The type of this event (GEVENT_AUDIO_PLAY)
+ */
+ GEventType type;
+ /**
+ * @brief The event flags
+ */
+ uint16_t flags;
+ /**
+ * @brief The event flag values.
+ * @{
+ */
+ #define GAUDIO_PLAY_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_PLAY event was lost */
+ #define GAUDIO_PLAY_PLAYING 0x0002 /**< @brief The audio out system is currently playing */
+ #define GAUDIO_PLAY_FREEBLOCK 0x0004 /**< @brief An audio buffer has been freed */
+ /** @} */
+ } GEventAudioPlay;
+ /** @} */
+
+ /**
+ * @brief The Audio record event structure.
+ * @{
+ */
+ typedef struct GEventAudioRecord_t {
+ /**
+ * @brief The type of this event (GEVENT_AUDIO_RECORD)
+ */
+ GEventType type;
+ /**
+ * @brief The event flags
+ */
+ uint16_t flags;
+ /**
+ * @brief The event flag values.
+ * @{
+ */
+ #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_STALL 0x0008 /**< @brief The recording process has stalled due to no free buffers */
+ /** @} */
+ } GEventAudioRecord;
+ /** @} */
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+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
+ * sample frequency.
+ * @return TRUE is successful, FALSE if the driver doesn't accept those parameters.
+ *
+ * @param[in] channel The audio output channel to use. Can be set from 0 to GAUDIO_PLAY_NUM_CHANNELS - 1
+ * @param[in] frequency The audio sample rate in samples per second
+ * @param[in] format The audio sample format
+ *
+ * @note Some channels are mono, and some are stereo. See your driver config file
+ * to determine which channels to use and whether they are stereo or not.
+ * @note Only one channel can be playing at a time. Calling this will stop any
+ * currently playing channel.
+ *
+ * @api
+ */
+ bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
+
+ /**
+ * @brief Play the specified sample data.
+ * @details The sample data is output to the audio channel. On completion the buffer is returned to the free-list.
+ * @pre @p gaudioPlayInit must have been called first to set the channel and sample frequency.
+ *
+ * @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
+ * 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
+ * can be obtained from the free-list), any number of buffers may be played. They will be queued
+ * for playing in the order they are supplied to this routine and played when previous buffers are
+ * complete. In this way continuous playing can be obtained without audio gaps.
+ *
+ * @api
+ */
+ void gaudioPlay(GAudioData *paud);
+
+ /**
+ * @brief Pause any currently playing sounds.
+ *
+ * @note If nothing is currently playing this routine does nothing. To restart playing call @p gaudioPlay()
+ * with or without a new sample buffer.
+ * @note Some drivers will not respond until a buffer boundary.
+ *
+ * @api
+ */
+ void gaudioPlayPause(void);
+
+ /**
+ * @brief Stop any currently playing sounds.
+ *
+ * @note This stops any playing sounds and returns any currently queued buffers back to the free-list.
+ * @note Some drivers will not respond until a buffer boundary.
+ *
+ * @api
+ */
+ void gaudioPlayStop(void);
+
+ /**
+ * @brief Set the output volume.
+ * @return TRUE if successful.
+ *
+ * @param[in] 0->255 (0 = muted)
+ *
+ * @note Some drivers may not support this. They will return FALSE.
+ * @note For stereo devices, both channels are set to the same volume.
+ *
+ * @api
+ */
+ bool_t gaudioPlaySetVolume(uint8_t vol);
+
+ #if GFX_USE_GEVENT || defined(__DOXYGEN__)
+ /**
+ * @brief Turn on sending results to the GEVENT sub-system.
+ * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_OUT events.
+ *
+ * @note The audio output will not use the GEVENT system unless this is
+ * called first. This saves processing time if the application does
+ * not want to use the GEVENT sub-system for audio output.
+ * Once turned on it can only be turned off by calling @p gaudioPlayInit() again.
+ * @note The audio output is capable of signaling via this method and other methods
+ * at the same time.
+ *
+ * @return The GSourceHandle
+ *
+ * @api
+ */
+ GSourceHandle gaudioPlayGetSource(void);
+ #endif
+
+ /**
+ * @brief Wait for any currently playing sounds to complete
+ * @return TRUE if there is now nothing playing or FALSE if the timeout is exceeded
+ *
+ * @params[in] ms The maximum amount of time in milliseconds to wait for playing to complete.
+ *
+ * @api
+ */
+ bool_t gaudioPlayWait(delaytime_t ms);
+#endif
+
+#if GAUDIO_NEED_RECORD || defined(__DOXYGEN__)
+ /**
+ * @brief Initialise (but not start) the Audio Recording sub-system.
+ * @details Returns FALSE for an invalid channel or other invalid parameter.
+ *
+ * @param[in] channel The channel to convert. Can be set from 0 to GAUDIO_RECORD_NUM_CHANNELS - 1
+ * @param[in] frequency The sample frequency
+ * @param[in] format The audio sample format requested
+ *
+ * @note Only one channel is active at a time. If an audio input is running it will be stopped.
+ * The Event subsystem is disconnected from the audio subsystem and any binary semaphore
+ * event is forgotten.
+ * @note Some channels may be stereo channels which return twice as much sample data with
+ * the left and right channel data interleaved. Other channels may be mono channels.
+ * Where stereo channels exist the low level driver may also
+ * offer the left and right channels separately.
+ * @note Due to a bug in Chibi-OS each buffer on the free-list must contain an even number of
+ * samples and for stereo devices it must hold a number of samples that is evenly divisible by 4.
+ * This requirement applies only to ChibiOS where the audio driver uses
+ * a ChibiOS hal driver like the cpu ADC driver. This applies even it is used indirectly via
+ * the uGFX GADC driver.
+ * @note The number of samples for stereo devices will be double the number of conversions.
+ * Make sure you allocate your buffers large enough. Each channel is then interleaved
+ * into the provided buffer.
+ *
+ * @return FALSE if invalid channel or parameter
+ *
+ * @api
+ */
+ bool_t gaudioRecordInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
+
+ /**
+ * @brief Start the audio recording.
+ * @pre It must have been initialised first with @p gaudioRecordInit()
+ *
+ * @api
+ */
+ void gaudioRecordStart(void);
+
+ /**
+ * @brief Stop the audio recording.
+ *
+ * @note All audio recording data that has not yet been retrieved is automatically
+ * returned to the free-list.
+ * @api
+ */
+ void gaudioRecordStop(void);
+
+ /**
+ * @brief Get a filled audio buffer from the recording 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 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().
+ * @api
+ */
+ GAudioData *gaudioRecordGetData(delaytime_t ms);
+
+ #if GFX_USE_GEVENT || defined(__DOXYGEN__)
+ /**
+ * @brief Turn on sending results to the GEVENT sub-system.
+ * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_RECORD events.
+ *
+ * @note Audio recording will not use the GEVENT system unless this is
+ * called first. This saves processing time if the application does
+ * not want to use the GEVENT sub-system for audio recording.
+ * Once turned on it can only be turned off by calling @p gaudioRecordInit() again.
+ * @note The audio input is capable of signaling via this and other methods
+ * at the same time.
+ *
+ * @return The GSourceHandle
+ *
+ * @api
+ */
+ GSourceHandle gaudioRecordGetSource(void);
+ #endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GAUDIO */
+
+#endif /* _GAUDIO_H */
+/** @} */
+
diff --git a/src/gaudio/sys_make.mk b/src/gaudio/sys_make.mk
new file mode 100644
index 00000000..438892c0
--- /dev/null
+++ b/src/gaudio/sys_make.mk
@@ -0,0 +1 @@
+GFXSRC += $(GFXLIB)/src/gaudio/gaudio.c
diff --git a/src/gaudio/sys_options.h b/src/gaudio/sys_options.h
new file mode 100644
index 00000000..1363d703
--- /dev/null
+++ b/src/gaudio/sys_options.h
@@ -0,0 +1,44 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gaudio/sys_options.h
+ * @brief GAUDIO - Audio subsystem options header file.
+ *
+ * @addtogroup GAUDIO
+ * @{
+ */
+
+#ifndef _GAUDIO_OPTIONS_H
+#define _GAUDOUT_OPTIONS_H
+
+/**
+ * @name GAUDIO Functionality to be included
+ * @{
+ */
+ /**
+ * @brief Audio Play capability is needed
+ */
+ #ifndef GAUDIO_NEED_PLAY
+ #define GAUDIO_NEED_PLAY FALSE
+ #endif
+ /**
+ * @brief Audio Recording capability is needed
+ */
+ #ifndef GAUDIO_NEED_RECORD
+ #define GAUDIO_NEED_RECORD FALSE
+ #endif
+/**
+ * @}
+ *
+ * @name GAUDIO Optional Sizing Parameters
+ * @{
+ */
+/** @} */
+
+#endif /* _GAUDIO_OPTIONS_H */
+/** @} */
diff --git a/src/gaudio/sys_rules.h b/src/gaudio/sys_rules.h
new file mode 100644
index 00000000..a3f0dffc
--- /dev/null
+++ b/src/gaudio/sys_rules.h
@@ -0,0 +1,54 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gaudio/sys_rules.h
+ * @brief GAUDIO safety rules header file.
+ *
+ * @addtogroup GAUDIO
+ * @{
+ */
+
+#ifndef _GAUDIO_RULES_H
+#define _GAUDIO_RULES_H
+
+#if GFX_USE_GAUDIO
+ #if !GAUDIO_NEED_PLAY && !GAUDIO_NEED_RECORD
+ #error "GAUDIO: GAUDIO_NEED_PLAY and/or GAUDIO_NEED_RECORD is required if GFX_USE_GAUDIO is TRUE"
+ #endif
+ #if !GFX_USE_GQUEUE
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GAUDIO: GFX_USE_GQUEUE is required if GFX_USE_GAUDIO is TRUE. It has been turned on for you."
+ #endif
+ #undef GFX_USE_GQUEUE
+ #define GFX_USE_GQUEUE TRUE
+ #endif
+ #if !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."
+ #endif
+ #undef GQUEUE_NEED_ASYNC
+ #define GQUEUE_NEED_ASYNC TRUE
+ #endif
+ #if !GQUEUE_NEED_GSYNC
+ #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."
+ #endif
+ #undef GQUEUE_NEED_GSYNC
+ #define GQUEUE_NEED_GSYNC TRUE
+ #endif
+ #if GFX_USE_GEVENT && !GFX_USE_GTIMER
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GAUDIO: GFX_USE_GTIMER is required if GFX_USE_GAUDIO and GFX_USE_GEVENT are TRUE. It has been turned on for you."
+ #endif
+ #undef GFX_USE_GTIMER
+ #define GFX_USE_GTIMER TRUE
+ #endif
+#endif
+
+#endif /* _GAUDIO_RULES_H */
+/** @} */
diff --git a/src/gaudout/gaudout.c b/src/gaudout/gaudout.c
deleted file mode 100644
index 00b01e91..00000000
--- a/src/gaudout/gaudout.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file src/gaudout/gaudout.c
- * @brief GAUDOUT sub-system code.
- *
- * @addtogroup GAUDOUT
- * @{
- */
-#include "gfx.h"
-
-#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
-
-#include "src/gaudout/driver.h"
-
-static gfxQueueASync playlist;
-static gfxQueueGSync freelist;
-
-static uint16_t PlayFlags;
- #define PLAYFLG_USEEVENTS 0x0001
- #define PLAYFLG_PLAYING 0x0002
-
-#if GFX_USE_GEVENT
- static GTimer PlayTimer;
-
- static void PlayTimerCallback(void *param) {
- (void) param;
- GSourceListener *psl;
- GEventAudioOut *pe;
-
- psl = 0;
- while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
- if (!(pe = (GEventAudioOut *)geventGetEventBuffer(psl))) {
- // This listener is missing - save this.
- psl->srcflags |= GAUDOUT_LOSTEVENT;
- continue;
- }
-
- pe->type = GEVENT_AUDIO_OUT;
- pe->flags = psl->srcflags;
- psl->srcflags = 0;
- if ((PlayFlags & PLAYFLG_PLAYING))
- pe->flags |= GAUDOUT_PLAYING;
- if (!gfxQueueGSyncIsEmpty(&freelist))
- pe->flags |= GAUDOUT_FREEBLOCK;
- geventSendEvent(psl);
- }
- }
-#endif
-
-
-void _gaudoutInit(void)
-{
- gfxQueueASyncInit(&playlist);
- gfxQueueGSyncInit(&freelist);
- #if GFX_USE_GEVENT
- gtimerInit(&PlayTimer);
- #endif
-}
-
-void _gaudoutDeinit(void)
-{
- /* ToDo */
- #if GFX_USE_GEVENT
- gtimerDeinit(&PlayTimer);
- #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);
-}
-
-bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
- gaudioPlayStop();
- gaudout_lld_deinit();
- return gaudout_lld_init(channel, frequency, format);
-}
-
-void gaudioPlay(GAudioData *paud) {
- if (paud)
- gfxQueueASyncPut(&playlist, (gfxQueueASyncItem *)paud);
- PlayFlags |= PLAYFLG_PLAYING;
- gaudout_lld_start();
-}
-
-void gaudioPlayPause(void) {
- gaudout_lld_stop();
-}
-
-void gaudioPlayStop(void) {
- GAudioData *paud;
-
- gaudout_lld_stop();
- while((paud = (GAudioData *)gfxQueueASyncGet(&playlist)))
- gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
- PlayFlags &= ~PLAYFLG_PLAYING;
-}
-
-bool_t gaudioPlaySetVolume(uint8_t vol) {
- return gaudout_lld_set_volume(vol);
-}
-
-#if GFX_USE_GEVENT || defined(__DOXYGEN__)
- GSourceHandle gaudioPlayGetSource(void) {
- if (!gtimerIsActive(&PlayTimer))
- gtimerStart(&PlayTimer, PlayTimerCallback, 0, TRUE, TIME_INFINITE);
- PlayFlags |= PLAYFLG_USEEVENTS;
- return (GSourceHandle)&PlayFlags;
- }
-#endif
-
-/**
- * Routines provided for use by drivers.
- */
-
-GAudioData *gaudoutGetDataBlockI(void) {
- return (GAudioData *)gfxQueueASyncGetI(&playlist);
-}
-
-void gaudoutReleaseDataBlockI(GAudioData *paud) {
- gfxQueueGSyncPutI(&freelist, (gfxQueueGSyncItem *)paud);
- #if GFX_USE_GEVENT
- if (PlayFlags & PLAYFLG_USEEVENTS)
- gtimerJabI(&PlayTimer);
- #endif
-}
-
-void gaudoutDoneI(void) {
- PlayFlags &= ~PLAYFLG_PLAYING;
- #if GFX_USE_GEVENT
- if (PlayFlags & PLAYFLG_USEEVENTS)
- gtimerJabI(&PlayTimer);
- #endif
-}
-
-#endif /* GFX_USE_GAUDOUT */
-/** @} */
-
diff --git a/src/gaudout/sys_defs.h b/src/gaudout/sys_defs.h
deleted file mode 100644
index 75cda243..00000000
--- a/src/gaudout/sys_defs.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file src/gaudout/sys_defs.h
- *
- * @addtogroup GAUDOUT
- *
- * @brief Module to output audio data (under development)
- *
- * @{
- */
-
-#ifndef _GAUDOUT_H
-#define _GAUDOUT_H
-
-#include "gfx.h"
-
-#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
-
-/* Include the driver defines */
-#include "gaudout_lld_config.h"
-
-
-/*===========================================================================*/
-/* 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 GAUDOUT
-#define GEVENT_AUDIO_OUT (GEVENT_GAUDOUT_FIRST+0)
-
-/**
- * @brief The Audio output event structure.
- * @{
- */
-typedef struct GEventAudioOut_t {
- #if GFX_USE_GEVENT || defined(__DOXYGEN__)
- /**
- * @brief The type of this event (GEVENT_AUDIO_OUT)
- */
- GEventType type;
- #endif
- /**
- * @brief The event flags
- */
- uint16_t flags;
- /**
- * @brief The event flag values.
- * @{
- */
- #define GAUDOUT_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_OUT event was lost */
- #define GAUDOUT_PLAYING 0x0002 /**< @brief The audio out system is currently playing */
- #define GAUDOUT_FREEBLOCK 0x0004 /**< @brief An audio buffer has been freed */
- /** @} */
-} GEventAudioOut;
-/** @} */
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#ifdef __cplusplus
-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);
-
-/**
- * @brief Set the audio device to play on the specified channel and with the specified
- * sample frequency.
- * @return TRUE is successful, FALSE if the driver doesn't accept those parameters.
- *
- * @param[in] channel The audio output channel to use.
- * @param[in] frequency The audio sample rate in samples per second
- * @param[in] format The audio sample format
- *
- * @note Some channels are mono, and some are stereo. See your driver config file
- * to determine which channels to use and whether they are stereo or not.
- * @note Only one channel can be playing at a time. Calling this will stop any
- * currently playing channel.
- *
- * @api
- */
-bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
-
-/**
- * @brief Play the specified sample data.
- * @details The sample data is output to the audio channel. On completion the buffer is returned to the free-list.
- * @pre @p gaudioPlayInit must have been called first to set the channel and sample frequency.
- *
- * @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
- * 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
- * can be obtained from the free-list), any number of buffers may be played. They will be queued
- * for playing in the order they are supplied to this routine and played when previous buffers are
- * complete. In this way continuous playing can be obtained without audio gaps.
- *
- * @api
- */
-void gaudioPlay(GAudioData *paud);
-
-/**
- * @brief Pause any currently playing sounds.
- *
- * @note If nothing is currently playing this routine does nothing. To restart playing call @p gaudioPlay()
- * with or without a new sample buffer.
- * @note Some drivers will not respond until a buffer boundary.
- *
- * @api
- */
-void gaudioPlayPause(void);
-
-/**
- * @brief Stop any currently playing sounds.
- *
- * @note This stops any playing sounds and returns any currently queued buffers back to the free-list.
- * @note Some drivers will not respond until a buffer boundary.
- *
- * @api
- */
-void gaudioPlayStop(void);
-
-/**
- * @brief Set the output volume.
- * @return TRUE if successful.
- *
- * @param[in] 0->255 (0 = muted)
- *
- * @note Some drivers may not support this. They will return FALSE.
- * @note For stereo devices, both channels are set to the same volume.
- *
- * @api
- */
-bool_t gaudioPlaySetVolume(uint8_t vol);
-
-#if GFX_USE_GEVENT || defined(__DOXYGEN__)
- /**
- * @brief Turn on sending results to the GEVENT sub-system.
- * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_OUT events.
- *
- * @note The audio output will not use the GEVENT system unless this is
- * called first. This saves processing time if the application does
- * not want to use the GEVENT sub-system for audio output.
- * Once turned on it can only be turned off by calling @p gaudioPlayInit() again.
- * @note The audio output is capable of signalling via this method and other methods
- * at the same time.
- *
- * @return The GSourceHandle
- *
- * @api
- */
- GSourceHandle gaudioPlayGetSource(void);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GFX_USE_GAUDOUT */
-
-#endif /* _GAUDOUT_H */
-/** @} */
-
diff --git a/src/gaudout/sys_make.mk b/src/gaudout/sys_make.mk
deleted file mode 100644
index 14f5bac3..00000000
--- a/src/gaudout/sys_make.mk
+++ /dev/null
@@ -1 +0,0 @@
-GFXSRC += $(GFXLIB)/src/gaudout/gaudout.c
diff --git a/src/gaudout/sys_options.h b/src/gaudout/sys_options.h
deleted file mode 100644
index 929bb42a..00000000
--- a/src/gaudout/sys_options.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file src/gaudout/sys_options.h
- * @brief GAUDOUT - Audio Output subsystem options header file.
- *
- * @addtogroup GAUDOUT
- * @{
- */
-
-#ifndef _GAUDOUT_OPTIONS_H
-#define _GAUDOUT_OPTIONS_H
-
-/**
- * @name GAUDOUT Functionality to be included
- * @{
- */
-/**
- * @}
- *
- * @name GAUDOUT Optional Sizing Parameters
- * @{
- */
-/** @} */
-
-#endif /* _GAUDOUT_OPTIONS_H */
-/** @} */
diff --git a/src/gaudout/sys_rules.h b/src/gaudout/sys_rules.h
deleted file mode 100644
index 8274e031..00000000
--- a/src/gaudout/sys_rules.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-/**
- * @file src/gaudout/sys_rules.h
- * @brief GAUDOUT safety rules header file.
- *
- * @addtogroup GAUDOUT
- * @{
- */
-
-#ifndef _GAUDOUT_RULES_H
-#define _GAUDOUT_RULES_H
-
-#if GFX_USE_GAUDOUT
- #if !GFX_USE_GQUEUE
- #if GFX_DISPLAY_RULE_WARNINGS
- #warning "GAUDOUT: GFX_USE_GQUEUE is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you."
- #endif
- #undef GFX_USE_GQUEUE
- #define GFX_USE_GQUEUE TRUE
- #endif
- #if !GQUEUE_NEED_ASYNC
- #if GFX_DISPLAY_RULE_WARNINGS
- #warning "GAUDOUT: GQUEUE_NEED_ASYNC is required if GFX_USE_GAUDOUT 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 GFX_DISPLAY_RULE_WARNINGS
- #warning "GAUDOUT: GQUEUE_NEED_GSYNC is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you."
- #endif
- #undef GQUEUE_NEED_GSYNC
- #define GQUEUE_NEED_GSYNC TRUE
- #endif
-#endif
-
-#endif /* _GAUDOUT_RULES_H */
-/** @} */
diff --git a/src/gevent/sys_defs.h b/src/gevent/sys_defs.h
index 0e656145..c50dc5ae 100644
--- a/src/gevent/sys_defs.h
+++ b/src/gevent/sys_defs.h
@@ -38,8 +38,7 @@ typedef uint16_t GEventType;
#define GEVENT_GINPUT_FIRST 0x0100 // GINPUT events range from 0x0100 to 0x01FF
#define GEVENT_GWIN_FIRST 0x0200 // GWIN events range from 0x0200 to 0x02FF
#define GEVENT_GADC_FIRST 0x0300 // GADC events range from 0x0300 to 0x033F
- #define GEVENT_GAUDIN_FIRST 0x0340 // GAUDIN events range from 0x0340 to 0x037F
- #define GEVENT_GAUDOUT_FIRST 0x0380 // GAUDOUT events range from 0x0380 to 0x03BF
+ #define GEVENT_GAUDIO_FIRST 0x0340 // GAUDIO events range from 0x0340 to 0x037F
#define GEVENT_USER_FIRST 0x8000 // Any application defined events start at 0x8000
// This object can be typecast to any GEventXxxxx type to allow any sub-system (or the application) to create events.
diff --git a/src/gfx.c b/src/gfx.c
index d01d3b1f..8e92fc29 100644
--- a/src/gfx.c
+++ b/src/gfx.c
@@ -44,13 +44,9 @@ extern void _gosDeinit(void);
extern void _gadcInit(void);
extern void _gadcDeinit(void);
#endif
-#if GFX_USE_GAUDIN
- extern void _gaudinInit(void);
- extern void _gaudinDeinit(void);
-#endif
-#if GFX_USE_GAUDOUT
- extern void _gaudoutInit(void);
- extern void _gaudoutDeinit(void);
+#if GFX_USE_GAUDIO
+ extern void _gaudioInit(void);
+ extern void _gaudioDeinit(void);
#endif
#if GFX_USE_GMISC
extern void _gmiscInit(void);
@@ -88,11 +84,8 @@ void gfxInit(void)
#if GFX_USE_GADC
_gadcInit();
#endif
- #if GFX_USE_GAUDIN
- _gaudinInit();
- #endif
- #if GFX_USE_GAUDOUT
- _gaudoutInit();
+ #if GFX_USE_GAUDIO
+ _gaudioInit();
#endif
}
@@ -103,11 +96,8 @@ void gfxDeinit(void)
initDone = FALSE;
// We deinitialise the opposite way as we initialised
- #if GFX_USE_GAUDOUT
- _gaudoutDeinit();
- #endif
#if GFX_USE_GAUDIN
- _gaudinDeinit();
+ _gaudioDeinit();
#endif
#if GFX_USE_GADC
_gadcDeinit();