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.
This commit is contained in:
parent
944c33cbff
commit
ea5a1b849d
@ -5,4 +5,4 @@ include $(GFXLIB)/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
|
|||||||
include $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.mk
|
include $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.mk
|
||||||
include $(GFXLIB)/drivers/ginput/dial/GADC/ginput_lld.mk
|
include $(GFXLIB)/drivers/ginput/dial/GADC/ginput_lld.mk
|
||||||
include $(GFXLIB)/drivers/ginput/toggle/Pal/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
|
||||||
|
@ -6,7 +6,7 @@ On this board uGFX currently supports:
|
|||||||
- GADC via the AT91SAM7 driver
|
- GADC via the AT91SAM7 driver
|
||||||
- GINPUT-dials via the GADC driver
|
- GINPUT-dials via the GADC driver
|
||||||
- GINPUT-toggles via the Pal 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
|
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.
|
and one with the GE12 display. This one is for the GE12 display.
|
||||||
|
@ -5,4 +5,4 @@ include $(GFXLIB)/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
|
|||||||
include $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.mk
|
include $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.mk
|
||||||
include $(GFXLIB)/drivers/ginput/dial/GADC/ginput_lld.mk
|
include $(GFXLIB)/drivers/ginput/dial/GADC/ginput_lld.mk
|
||||||
include $(GFXLIB)/drivers/ginput/toggle/Pal/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
|
||||||
|
@ -6,28 +6,28 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file boards/base/Olimex-SAM7EX256-GE8/gaudin_lld_board.h
|
* @file boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h
|
||||||
* @brief GAUDIN Driver board config file for the Olimex SAM7EX256 board
|
* @brief GAUDIO Record Driver board config file for the Olimex SAM7EX256 board
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _GAUDIN_LLD_BOARD_H
|
#ifndef _GAUDIO_RECORD_BOARD_H
|
||||||
#define _GAUDIN_LLD_BOARD_H
|
#define _GAUDIO_RECORD_BOARD_H
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Audio inputs on this board */
|
/* Audio inputs on this board */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
#define GAUDIN_NUM_CHANNELS 1
|
#define GAUDIO_RECORD_NUM_CHANNELS 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of audio channels and their uses
|
* The list of audio channels and their uses
|
||||||
*/
|
*/
|
||||||
#define GAUDIN_MICROPHONE 0
|
#define GAUDIO_RECORD_MICROPHONE 0
|
||||||
|
|
||||||
#ifdef GAUDIN_LLD_IMPLEMENTATION
|
#ifdef GAUDIO_RECORD_IMPLEMENTATION
|
||||||
static uint32_t gaudin_lld_physdevs[GAUDIN_NUM_CHANNELS] = {
|
static uint32_t gaudin_lld_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = {
|
||||||
GADC_PHYSDEV_MICROPHONE,
|
GADC_PHYSDEV_MICROPHONE,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _GAUDIN_LLD_BOARD_H */
|
#endif /* _GAUDIO_RECORD_BOARD_H */
|
@ -6,7 +6,7 @@ On this board uGFX currently supports:
|
|||||||
- GADC via the AT91SAM7 driver
|
- GADC via the AT91SAM7 driver
|
||||||
- GINPUT-dials via the GADC driver
|
- GINPUT-dials via the GADC driver
|
||||||
- GINPUT-toggles via the Pal 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
|
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.
|
and one with the GE12 display. This one is for the GE8 display.
|
||||||
|
@ -2,4 +2,4 @@ GFXINC += $(GFXLIB)/boards/base/Win32
|
|||||||
GFXSRC +=
|
GFXSRC +=
|
||||||
|
|
||||||
include $(GFXLIB)/drivers/multiple/Win32/driver.mk
|
include $(GFXLIB)/drivers/multiple/Win32/driver.mk
|
||||||
include $(GFXLIB)/drivers/audio/Win32/driver.mk
|
include $(GFXLIB)/drivers/gaudio/Win32/driver.mk
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
DEMODIR = $(GFXLIB)/demos/modules/audio/oscilloscope
|
DEMODIR = $(GFXLIB)/demos/modules/gaudio/oscilloscope
|
||||||
GFXINC += $(DEMODIR)
|
GFXINC += $(DEMODIR)
|
||||||
GFXSRC += $(DEMODIR)/main.c $(DEMODIR)/gwinosc.c
|
GFXSRC += $(DEMODIR)/main.c $(DEMODIR)/gwinosc.c
|
@ -46,11 +46,14 @@
|
|||||||
#define GFX_USE_GWIN TRUE
|
#define GFX_USE_GWIN TRUE
|
||||||
#define GFX_USE_GTIMER TRUE
|
#define GFX_USE_GTIMER TRUE
|
||||||
//#define GFX_USE_GADC TRUE
|
//#define GFX_USE_GADC TRUE
|
||||||
#define GFX_USE_GAUDIN TRUE
|
#define GFX_USE_GAUDIO TRUE
|
||||||
|
|
||||||
/* Features for the GDISP sub-system. */
|
/* Features for the GDISP sub-system. */
|
||||||
#define GDISP_NEED_VALIDATION TRUE
|
#define GDISP_NEED_VALIDATION TRUE
|
||||||
#define GDISP_NEED_CLIP TRUE
|
#define GDISP_NEED_CLIP TRUE
|
||||||
#define GDISP_NEED_MULTITHREAD TRUE
|
#define GDISP_NEED_MULTITHREAD TRUE
|
||||||
|
|
||||||
|
/* Features for the GAUDIO sub-system */
|
||||||
|
#define GAUDIO_NEED_RECORD TRUE
|
||||||
|
|
||||||
#endif /* _GFXCONF_H */
|
#endif /* _GFXCONF_H */
|
@ -32,8 +32,8 @@
|
|||||||
*
|
*
|
||||||
* This GWIN superset implements a simple audio oscilloscope using the GAUDIN module.
|
* 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
|
* It makes many assumptions, the most fundamental of which is that the audio data
|
||||||
* produces unsigned integer samples.
|
* should be scaled to SCOPE_Y_BITS.
|
||||||
*
|
*
|
||||||
* The GMISC module with GMISC_NEED_ARRAYOPS could be used to process the samples more
|
* The GMISC module with GMISC_NEED_ARRAYOPS could be used to process the samples more
|
||||||
* correctly if we were really building something generic.
|
* 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 internal GWIN routines so we can build our own superset class */
|
||||||
#include "src/gwin/class_gwin.h"
|
#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 */
|
/* How many flat-line sample before we trigger */
|
||||||
#define FLATLINE_SAMPLES 8
|
#define FLATLINE_SAMPLES 8
|
||||||
|
|
||||||
static void _destroy(GHandle gh) {
|
static void _destroy(GHandle gh) {
|
||||||
gaudinStop();
|
gaudioRecordStop();
|
||||||
if (((GScopeObject *)gh)->lastscopetrace) {
|
if (((GScopeObject *)gh)->lastscopetrace) {
|
||||||
gfxFree(((GScopeObject *)gh)->lastscopetrace);
|
gfxFree(((GScopeObject *)gh)->lastscopetrace);
|
||||||
((GScopeObject *)gh)->lastscopetrace = 0;
|
((GScopeObject *)gh)->lastscopetrace = 0;
|
||||||
}
|
}
|
||||||
if (((GScopeObject *)gh)->audiobuf) {
|
|
||||||
gfxFree(((GScopeObject *)gh)->audiobuf);
|
|
||||||
((GScopeObject *)gh)->audiobuf = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gwinVMT scopeVMT = {
|
static const gwinVMT scopeVMT = {
|
||||||
@ -71,127 +64,136 @@ static const gwinVMT scopeVMT = {
|
|||||||
0, // The after-clear routine
|
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 */
|
/* Initialise the base class GWIN */
|
||||||
if (!(gs = (GScopeObject *)_gwindowCreate(g, &gs->g, pInit, &scopeVMT, 0)))
|
if (!(gs = (GScopeObject *)_gwindowCreate(g, &gs->g, pInit, &scopeVMT, 0)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Initialise the scope object members and allocate memory for buffers */
|
/* Initialise the scope object members and allocate memory for buffers */
|
||||||
gfxSemInit(&gs->bsem, 0, 1);
|
gs->format = format;
|
||||||
gs->nextx = 0;
|
gs->nextx = 0;
|
||||||
if (!(gs->lastscopetrace = (coord_t *)gfxAlloc(gs->g.width * sizeof(coord_t))))
|
if (!(gs->lastscopetrace = (coord_t *)gfxAlloc(gs->g.width * sizeof(coord_t))))
|
||||||
return 0;
|
return 0;
|
||||||
if (!(gs->audiobuf = (audin_sample_t *)gfxAlloc(AUDIOBUFSZ * sizeof(audin_sample_t))))
|
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
|
||||||
return 0;
|
gs->lasty = gs->g.height/2;
|
||||||
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
|
#elif TRIGGER_METHOD == TRIGGER_MINVALUE
|
||||||
gs->lasty = gs->g.height/2;
|
gs->lasty = gs->g.height/2;
|
||||||
#elif TRIGGER_METHOD == TRIGGER_MINVALUE
|
gs->scopemin = 0;
|
||||||
gs->lasty = gs->g.height/2;
|
#endif
|
||||||
gs->scopemin = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Start the GADC high speed converter */
|
|
||||||
gaudinInit(channel, frequency, gs->audiobuf, AUDIOBUFSZ, AUDIOBUFSZ/2);
|
|
||||||
gaudinSetBSem(&gs->bsem, &gs->myEvent);
|
|
||||||
gaudinStart();
|
|
||||||
|
|
||||||
|
/* Set visibility */
|
||||||
gwinSetVisible((GHandle)gs, pInit->show);
|
gwinSetVisible((GHandle)gs, pInit->show);
|
||||||
|
|
||||||
|
/* Start the audio recording */
|
||||||
|
gaudioRecordStart();
|
||||||
|
|
||||||
return (GHandle)gs;
|
return (GHandle)gs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gwinScopeWaitForTrace(GHandle gh) {
|
void gwinScopeWaitForTrace(GHandle gh) {
|
||||||
#define gs ((GScopeObject *)(gh))
|
#define gs ((GScopeObject *)(gh))
|
||||||
|
GAudioData *paud;
|
||||||
int i;
|
int i;
|
||||||
coord_t x, y;
|
coord_t x, y;
|
||||||
coord_t yoffset;
|
coord_t yoffset;
|
||||||
audin_sample_t *pa;
|
uint8_t *pa8;
|
||||||
|
uint16_t *pa16;
|
||||||
coord_t *pc;
|
coord_t *pc;
|
||||||
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
|
uint8_t shr;
|
||||||
bool_t rdytrigger;
|
|
||||||
int flsamples;
|
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
|
||||||
#elif TRIGGER_METHOD == TRIGGER_MINVALUE
|
bool_t rdytrigger;
|
||||||
bool_t rdytrigger;
|
int flsamples;
|
||||||
int flsamples;
|
#elif TRIGGER_METHOD == TRIGGER_MINVALUE
|
||||||
coord_t scopemin;
|
bool_t rdytrigger;
|
||||||
#endif
|
int flsamples;
|
||||||
|
coord_t scopemin;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (gh->vmt != &scopeVMT)
|
if (gh->vmt != &scopeVMT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Wait for a set of audio conversions */
|
/* Wait for a set of audio conversions */
|
||||||
gfxSemWait(&gs->bsem, TIME_INFINITE);
|
paud = gaudioRecordGetData(TIME_INFINITE);
|
||||||
|
|
||||||
/* Ensure we are drawing in the right area */
|
/* Ensure we are drawing in the right area */
|
||||||
#if GDISP_NEED_CLIP
|
#if GDISP_NEED_CLIP
|
||||||
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
|
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
shr = 16 - gfxSampleFormatBits(gs->format);
|
||||||
yoffset = gh->height/2;
|
yoffset = gh->height/2;
|
||||||
if (!(GAUDIN_SAMPLE_FORMAT & 1))
|
if (!gfxSampleFormatIsSigned(gs->format))
|
||||||
yoffset += (1<<SCOPE_Y_BITS)/2;
|
yoffset += (1<<SCOPE_Y_BITS)/2;
|
||||||
|
|
||||||
x = gs->nextx;
|
x = gs->nextx;
|
||||||
pc = gs->lastscopetrace+x;
|
pc = gs->lastscopetrace+x;
|
||||||
pa = gs->myEvent.buffer;
|
pa8 = (uint8_t *)(paud+1);
|
||||||
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
|
pa16 = (uint16_t *)(paud+1);
|
||||||
rdytrigger = FALSE;
|
|
||||||
flsamples = 0;
|
|
||||||
#elif TRIGGER_METHOD == TRIGGER_MINVALUE
|
|
||||||
rdytrigger = FALSE;
|
|
||||||
flsamples = 0;
|
|
||||||
scopemin = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for(i = gs->myEvent.count; i; i--) {
|
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
|
||||||
|
rdytrigger = FALSE;
|
||||||
|
flsamples = 0;
|
||||||
|
#elif TRIGGER_METHOD == TRIGGER_MINVALUE
|
||||||
|
rdytrigger = FALSE;
|
||||||
|
flsamples = 0;
|
||||||
|
scopemin = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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 */
|
/* 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
|
if (gs->format <= 8)
|
||||||
y = yoffset - (*pa++ >> (GAUDIN_BITS_PER_SAMPLE - SCOPE_Y_BITS));
|
y = yoffset - (((coord_t)(*pa8++ ) << shr) >> (16-SCOPE_Y_BITS));
|
||||||
#else
|
else
|
||||||
y = yoffset - (*pa++ << (SCOPE_Y_BITS - GAUDIN_BITS_PER_SAMPLE));
|
y = yoffset - (((coord_t)(*pa16++) << shr) >> (16-SCOPE_Y_BITS));
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TRIGGER_METHOD == TRIGGER_MINVALUE
|
#if TRIGGER_METHOD == TRIGGER_MINVALUE
|
||||||
/* Calculate the scopemin ready for the next trace */
|
/* Calculate the scopemin ready for the next trace */
|
||||||
if (y > scopemin)
|
if (y > scopemin)
|
||||||
scopemin = y;
|
scopemin = y;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Have we reached the end of a scope trace? */
|
/* Have we reached the end of a scope trace? */
|
||||||
if (x >= gh->width) {
|
if (x >= gh->width) {
|
||||||
|
|
||||||
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP || TRIGGER_METHOD == TRIGGER_MINVALUE
|
#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 */
|
/* Handle triggering - we trigger on the next sample minimum (y value maximum) or a flat-line */
|
||||||
|
|
||||||
#if TRIGGER_METHOD == TRIGGER_MINVALUE
|
#if TRIGGER_METHOD == TRIGGER_MINVALUE
|
||||||
/* Arm when we reach the sample minimum (y value maximum) of the previous trace */
|
/* Arm when we reach the sample minimum (y value maximum) of the previous trace */
|
||||||
if (!rdytrigger && y >= gs->scopemin)
|
if (!rdytrigger && y >= gs->scopemin)
|
||||||
rdytrigger = TRUE;
|
rdytrigger = TRUE;
|
||||||
#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
|
#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 */
|
if (y == gs->lasty) {
|
||||||
rdytrigger = FALSE;
|
/* Trigger if we get too many flat-line samples regardless of the armed state */
|
||||||
#endif
|
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 */
|
/* Prepare for a scope trace */
|
||||||
x = 0;
|
x = 0;
|
||||||
@ -214,5 +216,6 @@ void gwinScopeWaitForTrace(GHandle gh) {
|
|||||||
gs->scopemin = scopemin;
|
gs->scopemin = scopemin;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
gaudioReleaseBuffer(paud);
|
||||||
#undef gs
|
#undef gs
|
||||||
}
|
}
|
@ -64,9 +64,7 @@ typedef struct GScopeObject_t {
|
|||||||
GWindowObject g; // Base Class
|
GWindowObject g; // Base Class
|
||||||
|
|
||||||
coord_t *lastscopetrace; // To store last scope trace
|
coord_t *lastscopetrace; // To store last scope trace
|
||||||
gfxSem bsem; // We get signalled on this
|
ArrayDataFormat format; // The sample format
|
||||||
audin_sample_t *audiobuf; // To store audio samples
|
|
||||||
GEventAudioIn myEvent; // Information on received samples
|
|
||||||
coord_t nextx; // Where we are up to
|
coord_t nextx; // Where we are up to
|
||||||
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
|
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
|
||||||
coord_t lasty; // The last y value - used for trigger slope detection
|
coord_t lasty; // The last y value - used for trigger slope detection
|
||||||
@ -83,8 +81,8 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* Create a scope window.
|
* Create a scope window.
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
#define gwinScopeCreate(gs,pI,ch,f) gwinGScopeCreate(GDISP,gs,pI,ch,f)
|
#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.
|
* Wait for a scope trace to be ready and then draw it.
|
@ -39,8 +39,9 @@
|
|||||||
#include "gwinosc.h"
|
#include "gwinosc.h"
|
||||||
|
|
||||||
/* Specify our timing parameters */
|
/* Specify our timing parameters */
|
||||||
#define MY_AUDIO_FREQUENCY 4000 /* 4khz */
|
#define MY_AUDIO_FREQUENCY 8000 /* 8khz. If this is too much try 4000 (4khz) */
|
||||||
#define MY_AUDIO_CHANNEL 0 /* Use channel 0 */
|
#define MY_AUDIO_CHANNEL 0 /* Use channel 0 - must be a mono channel */
|
||||||
|
#define MY_AUDIO_FORMAT GAUDIO_RECORD_FORMAT1 /* The default format */
|
||||||
|
|
||||||
/* Data */
|
/* Data */
|
||||||
static GScopeObject gScopeWindow;
|
static GScopeObject gScopeWindow;
|
||||||
@ -54,6 +55,11 @@ int main(void) {
|
|||||||
|
|
||||||
gfxInit();
|
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 */
|
/* Get the screen dimensions */
|
||||||
swidth = gdispGetWidth();
|
swidth = gdispGetWidth();
|
||||||
sheight = gdispGetHeight();
|
sheight = gdispGetHeight();
|
||||||
@ -65,7 +71,7 @@ int main(void) {
|
|||||||
wi.show = TRUE;
|
wi.show = TRUE;
|
||||||
wi.x = wi.y = 0;
|
wi.x = wi.y = 0;
|
||||||
wi.width = swidth; wi.height = sheight;
|
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);
|
gwinSetBgColor(ghScope, White);
|
||||||
gwinSetColor(ghScope, Red);
|
gwinSetColor(ghScope, Red);
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
@ -1,3 +1,3 @@
|
|||||||
DEMODIR = $(GFXLIB)/demos/modules/audio/play-wave
|
DEMODIR = $(GFXLIB)/demos/modules/gaudio/play-wave
|
||||||
GFXINC += $(DEMODIR)
|
GFXINC += $(DEMODIR)
|
||||||
GFXSRC += $(DEMODIR)/main.c
|
GFXSRC += $(DEMODIR)/main.c
|
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
/* GFX sub-systems to turn on */
|
/* GFX sub-systems to turn on */
|
||||||
#define GFX_USE_GDISP TRUE
|
#define GFX_USE_GDISP TRUE
|
||||||
#define GFX_USE_GAUDOUT TRUE
|
#define GFX_USE_GAUDIO TRUE
|
||||||
#define GFX_USE_GFILE TRUE
|
#define GFX_USE_GFILE TRUE
|
||||||
|
|
||||||
/* Features for the GDISP sub-system. */
|
/* Features for the GDISP sub-system. */
|
||||||
@ -53,6 +53,9 @@
|
|||||||
/* GDISP fonts to include */
|
/* GDISP fonts to include */
|
||||||
#define GDISP_INCLUDE_FONT_UI2 TRUE
|
#define GDISP_INCLUDE_FONT_UI2 TRUE
|
||||||
|
|
||||||
|
/* Features for the GAUDIO sub-system */
|
||||||
|
#define GAUDIO_NEED_PLAY TRUE
|
||||||
|
|
||||||
/* Features for the GFILE sub-system */
|
/* Features for the GFILE sub-system */
|
||||||
#define GFILE_NEED_ROMFS TRUE
|
#define GFILE_NEED_ROMFS TRUE
|
||||||
|
|
@ -34,8 +34,8 @@
|
|||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
|
|
||||||
/* Specify our timing parameters */
|
/* Specify our timing parameters */
|
||||||
#define MY_AUDIO_CHANNEL 0 /* Use channel 0 */
|
#define MY_AUDIO_CHANNEL 0 /* Use channel 0 */
|
||||||
#define MY_AUDIO_CHANNEL_IS_STEREO GAUDOUT_CHANNEL0_STEREO /* Is it stereo? */
|
#define MY_AUDIO_CHANNEL_IS_STEREO GAUDOUT_CHANNEL0_IS_STEREO /* Is it stereo? */
|
||||||
|
|
||||||
// Storage for the wave header
|
// Storage for the wave header
|
||||||
static char whdr[32];
|
static char whdr[32];
|
||||||
@ -61,7 +61,9 @@ int main(void) {
|
|||||||
// Any font will do
|
// Any font will do
|
||||||
font = gdispOpenFont("*");
|
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)) {
|
if (!gaudioAllocBuffers(4, 512)) {
|
||||||
errmsg = "Err: No Memory";
|
errmsg = "Err: No Memory";
|
||||||
goto theend;
|
goto theend;
|
||||||
@ -179,8 +181,8 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
gfileClose(f);
|
gfileClose(f);
|
||||||
|
|
||||||
// Wait 3 seconds for the play to finish - FIX THIS
|
// Wait for the play to finish
|
||||||
gfxSleepMilliseconds(3000);
|
gaudioPlayWait(TIME_INFINITE);
|
||||||
gdispDrawString(0, gdispGetHeight()/2+10, "Done", font, Green);
|
gdispDrawString(0, gdispGetHeight()/2+10, "Done", font, Green);
|
||||||
|
|
||||||
// The end
|
// The end
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* This file was generated from "allwrong.wav" using...
|
* 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[] = {
|
static const char allwrong[] = {
|
@ -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
|
|
@ -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 */
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
@ -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.
|
|
@ -1,5 +0,0 @@
|
|||||||
# List the required driver.
|
|
||||||
GFXSRC += $(GFXLIB)/drivers/gaudin/gadc/gaudin_lld.c
|
|
||||||
|
|
||||||
# Required include directories
|
|
||||||
GFXINC += $(GFXLIB)/drivers/audio/gadc
|
|
6
drivers/gaudio/Win32/driver.mk
Normal file
6
drivers/gaudio/Win32/driver.mk
Normal file
@ -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
|
@ -6,17 +6,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file drivers/audio/Win32/gaudout_lld_config.h
|
* @file drivers/gaudio/Win32/gaudio_play_config.h
|
||||||
* @brief GAUDOUT Driver config file.
|
* @brief GAUDIO Play Driver config file.
|
||||||
*
|
*
|
||||||
* @addtogroup GAUDOUT
|
* @addtogroup GAUDIO
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GAUDOUT_LLD_CONFIG_H
|
#ifndef GAUDIO_PLAY_CONFIG_H
|
||||||
#define GAUDIN_LLD_CONFIG_H
|
#define GAUDIO_PLAY_CONFIG_H
|
||||||
|
|
||||||
#if GFX_USE_GAUDOUT
|
#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver hardware support. */
|
/* Driver hardware support. */
|
||||||
@ -25,39 +25,39 @@
|
|||||||
/**
|
/**
|
||||||
* @brief The maximum sample frequency supported by this audio device
|
* @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
|
* @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
|
* @brief The available audio sample formats in order of preference
|
||||||
*/
|
*/
|
||||||
#define GAUDOUT_FORMAT1 ARRAY_DATA_16BITSIGNED
|
#define GAUDIO_PLAY_FORMAT1 ARRAY_DATA_16BITSIGNED
|
||||||
#define GAUDOUT_FORMAT2 ARRAY_DATA_8BITUNSIGNED
|
#define GAUDIO_PLAY_FORMAT2 ARRAY_DATA_8BITUNSIGNED
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The number of audio channels supported by this driver
|
* @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
|
* @brief Whether each channel is mono or stereo
|
||||||
*/
|
*/
|
||||||
#define GAUDOUT_CHANNEL0_STEREO FALSE
|
#define GAUDIO_PLAY_CHANNEL0_IS_STEREO FALSE
|
||||||
#define GAUDOUT_CHANNEL1_STEREO TRUE
|
#define GAUDIO_PLAY_CHANNEL1_IS_STEREO TRUE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The list of audio channel names and their uses
|
* @brief The list of audio channel names and their uses
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define GAUDOUT_MONO 0
|
#define GAUDIO_PLAY_MONO 0
|
||||||
#define GAUDOUT_STEREO 1
|
#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 */
|
||||||
/** @} */
|
/** @} */
|
@ -6,16 +6,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file drivers/audio/Win32/gaudout_lld.c
|
* @file drivers/gaudio/Win32/gaudio_play_lld.c
|
||||||
* @brief GAUDOUT - Driver file for Win32.
|
* @brief GAUDIO - Play Driver file for Win32.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
|
|
||||||
#if GFX_USE_GAUDOUT
|
#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY
|
||||||
|
|
||||||
/* Include the driver defines */
|
/* Include the driver defines */
|
||||||
#include "src/gaudout/driver.h"
|
#include "src/gaudio/driver_play.h"
|
||||||
|
|
||||||
#undef Red
|
#undef Red
|
||||||
#undef Green
|
#undef Green
|
||||||
@ -36,20 +36,6 @@ static WAVEHDR WaveHdrs[MAX_WAVE_HEADERS];
|
|||||||
static HANDLE waveThread;
|
static HANDLE waveThread;
|
||||||
static DWORD threadID;
|
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() *******************************
|
/**************************** waveProc() *******************************
|
||||||
* We don't use CALLBACK_FUNCTION because it is restricted to calling only
|
* We don't use CALLBACK_FUNCTION because it is restricted to calling only
|
||||||
* a few particular Windows functions, namely some of the time functions,
|
* 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
|
// Get the next data block to send
|
||||||
gfxSystemLock();
|
gfxSystemLock();
|
||||||
paud = gaudoutGetDataBlockI();
|
paud = gaudioPlayGetDataBlockI();
|
||||||
|
if (!paud && !nQueuedBuffers)
|
||||||
|
gaudioPlayDoneI();
|
||||||
gfxSystemUnlock();
|
gfxSystemUnlock();
|
||||||
if (!paud)
|
if (!paud)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -77,13 +65,13 @@ static bool_t senddata(WAVEHDR *pwh) {
|
|||||||
pwh->dwFlags = 0;
|
pwh->dwFlags = 0;
|
||||||
pwh->dwLoops = 0;
|
pwh->dwLoops = 0;
|
||||||
if (waveOutPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
|
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);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send it to windows
|
// Send it to windows
|
||||||
if (waveOutWrite(ah, pwh, sizeof(WAVEHDR))) {
|
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);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,18 +94,25 @@ static DWORD WINAPI waveProc(LPVOID arg) {
|
|||||||
|
|
||||||
// Give the buffer back to the Audio Free List
|
// Give the buffer back to the Audio Free List
|
||||||
gfxSystemLock();
|
gfxSystemLock();
|
||||||
gaudoutReleaseDataBlockI((GAudioData *)pwh->dwUser);
|
gaudioPlayReleaseDataBlockI((GAudioData *)pwh->dwUser);
|
||||||
gfxSystemUnlock();
|
gfxSystemUnlock();
|
||||||
pwh->lpData = 0;
|
pwh->lpData = 0;
|
||||||
nQueuedBuffers--;
|
nQueuedBuffers--;
|
||||||
|
|
||||||
// Try and get a new block
|
// Are we stopping?
|
||||||
if ((!isRunning || !senddata(pwh)) && !nQueuedBuffers) {
|
if (!isRunning) {
|
||||||
gfxSystemLock();
|
// Have we finished yet?
|
||||||
gaudoutDoneI();
|
if (!nQueuedBuffers) {
|
||||||
gfxSystemUnlock();
|
gfxSystemLock();
|
||||||
|
gaudioPlayDoneI();
|
||||||
|
gfxSystemUnlock();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
// Try and get a new block
|
||||||
|
senddata(pwh);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -127,17 +122,7 @@ static DWORD WINAPI waveProc(LPVOID arg) {
|
|||||||
/* External declarations. */
|
/* External declarations. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
void gaudout_lld_deinit() {
|
bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
|
||||||
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) {
|
|
||||||
WAVEFORMATEX wfx;
|
WAVEFORMATEX wfx;
|
||||||
|
|
||||||
if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_16BITSIGNED)
|
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) {
|
||||||
if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
|
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);
|
exit(-1);
|
||||||
}
|
}
|
||||||
CloseHandle(waveThread);
|
CloseHandle(waveThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
wfx.nChannels = channel == GAUDOUT_STEREO ? 2 : 1;
|
wfx.nChannels = channel == GAUDIO_PLAY_STEREO ? 2 : 1;
|
||||||
wfx.nSamplesPerSec = frequency;
|
wfx.nSamplesPerSec = frequency;
|
||||||
wfx.nBlockAlign = wfx.nChannels * (format == ARRAY_DATA_8BITUNSIGNED ? 1 : 2);
|
wfx.nBlockAlign = wfx.nChannels * (format == ARRAY_DATA_8BITUNSIGNED ? 1 : 2);
|
||||||
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
||||||
wfx.wBitsPerSample = (format == ARRAY_DATA_8BITUNSIGNED ? 8 : 16);
|
wfx.wBitsPerSample = (format == ARRAY_DATA_8BITUNSIGNED ? 8 : 16);
|
||||||
wfx.cbSize = 0;
|
wfx.cbSize = 0;
|
||||||
|
|
||||||
|
if (ah) {
|
||||||
|
waveOutClose(ah);
|
||||||
|
ah = 0;
|
||||||
|
}
|
||||||
if (waveOutOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
|
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);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t gaudout_lld_set_volume(uint8_t vol) {
|
bool_t gaudio_play_lld_set_volume(uint8_t vol) {
|
||||||
if (!ah)
|
if (!ah)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return waveOutSetVolume(ah, (((uint16_t)vol)<<8)|vol) != 0;
|
return waveOutSetVolume(ah, (((uint16_t)vol)<<8)|vol) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gaudout_lld_start(void) {
|
void gaudio_play_lld_start(void) {
|
||||||
WAVEHDR *pwh;
|
WAVEHDR *pwh;
|
||||||
|
|
||||||
if (!ah)
|
|
||||||
return;
|
|
||||||
|
|
||||||
isRunning = TRUE;
|
isRunning = TRUE;
|
||||||
while (nQueuedBuffers < MAX_WAVE_HEADERS) {
|
while (nQueuedBuffers < MAX_WAVE_HEADERS) {
|
||||||
// Find the empty one - there will always be at least one.
|
// 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;
|
isRunning = FALSE;
|
||||||
if (ah)
|
waveOutReset(ah);
|
||||||
waveOutReset(ah);
|
while(nQueuedBuffers) Sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* GFX_USE_GAUDOUT */
|
#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
|
63
drivers/gaudio/Win32/gaudio_record_config.h
Normal file
63
drivers/gaudio/Win32/gaudio_record_config.h
Normal file
@ -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 */
|
||||||
|
/** @} */
|
187
drivers/gaudio/Win32/gaudio_record_lld.c
Normal file
187
drivers/gaudio/Win32/gaudio_record_lld.c
Normal file
@ -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 */
|
10
drivers/gaudio/Win32/readme.txt
Normal file
10
drivers/gaudio/Win32/readme.txt
Normal file
@ -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.
|
5
drivers/gaudio/gadc/driver.mk
Normal file
5
drivers/gaudio/gadc/driver.mk
Normal file
@ -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
|
@ -6,15 +6,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file drivers/gaudin/gadc/gaudin_lld_board_template.h
|
* @file drivers/gaudio/gadc/gaudio_record_board_template.h
|
||||||
* @brief GAUDIN Driver board config board file
|
* @brief GAUDIO Record Driver board config board file
|
||||||
*
|
*
|
||||||
* @addtogroup GAUDIN
|
* @addtogroup GAUDIO
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _GAUDIN_LLD_BOARD_H
|
#ifndef _GAUDIO_RECORD_BOARD_H
|
||||||
#define _GAUDIN_LLD_BOARD_H
|
#define _GAUDIO_RECORD_BOARD_H
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Audio inputs on this board */
|
/* Audio inputs on this board */
|
||||||
@ -24,14 +24,14 @@
|
|||||||
* @brief The number of audio channels supported by this driver
|
* @brief The number of audio channels supported by this driver
|
||||||
* @note This is an example
|
* @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
|
* @brief The list of audio channels and their uses
|
||||||
* @note This is an example
|
* @note This is an example
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define GAUDIN_MICROPHONE 0
|
#define GAUDIO_RECORD_MICROPHONE 0
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,12 +39,12 @@
|
|||||||
* @note This is an example
|
* @note This is an example
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#ifdef GAUDIN_LLD_IMPLEMENTATION
|
#ifdef GAUDIO_RECORD_LLD_IMPLEMENTATION
|
||||||
static uint32_t gaudin_lld_physdevs[GAUDIN_NUM_CHANNELS] = {
|
static uint32_t gaudin_lld_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = {
|
||||||
GADC_PHYSDEV_MICROPHONE,
|
GADC_PHYSDEV_MICROPHONE,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#endif /* _GAUDIN_LLD_BOARD_H */
|
#endif /* _GAUDIO_RECORD_BOARD_H */
|
||||||
/** @} */
|
/** @} */
|
@ -6,54 +6,54 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file drivers/gaudin/gadc/gaudin_lld_config.h
|
* @file drivers/gaudio/gadc/gaudio_record_config.h
|
||||||
* @brief GAUDIN Driver config file.
|
* @brief GAUDIN Record Driver config file.
|
||||||
*
|
*
|
||||||
* @addtogroup GAUDIN
|
* @addtogroup GAUDIO
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GAUDIN_LLD_CONFIG_H
|
#ifndef GAUDIO_RECORD_CONFIG_H
|
||||||
#define GAUDIN_LLD_CONFIG_H
|
#define GAUDIO_RECORD_CONFIG_H
|
||||||
|
|
||||||
#if GFX_USE_GAUDIN
|
#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver hardware support. */
|
/* 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
|
* @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
|
* @brief The maximum sample frequency supported by this audio device
|
||||||
* @details For this driver it matches the GADC maximum high speed sample rate
|
* @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
|
* @brief The number of bits in a sample
|
||||||
* @details For this driver it matches the cpu sample bits
|
* @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
|
* @brief The format of an audio sample
|
||||||
* @details For this driver it matches the cpu sample format
|
* @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.
|
* to the board.
|
||||||
*/
|
*/
|
||||||
/* Include the user supplied board definitions */
|
/* 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 */
|
||||||
/** @} */
|
/** @} */
|
@ -6,10 +6,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file drivers/gaudin/gadc/gaudin_lld.c
|
* @file drivers/gaudio/gadc/gaudio_record_lld.c
|
||||||
* @brief GAUDIN - Driver file for using the cpu ADC (via GADC).
|
* @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
|
* We are now implementing the driver - pull in our channel table
|
||||||
* from the board definitions.
|
* from the board definitions.
|
||||||
*/
|
*/
|
||||||
#define GAUDIN_LLD_IMPLEMENTATION
|
#define GAUDIO_RECORD_IMPLEMENTATION
|
||||||
|
|
||||||
|
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
|
|
||||||
#if GFX_USE_GAUDIN
|
#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
|
||||||
|
|
||||||
/* Double check the GADC system is turned on */
|
/* Double check the GADC system is turned on */
|
||||||
#if !GFX_USE_GADC
|
#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
|
#endif
|
||||||
|
|
||||||
/* Include the driver defines */
|
/* Include the driver defines */
|
||||||
#include "src/gaudin/driver.h"
|
#include "src/gaudio/driver_record.h"
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* External declarations. */
|
/* External declarations. */
|
||||||
@ -58,5 +58,5 @@ void gaudin_lld_stop(void) {
|
|||||||
gadcHighSpeedStop();
|
gadcHighSpeedStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* GFX_USE_GAUDIN */
|
#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
|
||||||
/** @} */
|
/** @} */
|
@ -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.
|
It supports whatever high speed device channels that your GADC driver and board supports.
|
||||||
|
|
35
gfx.h
35
gfx.h
@ -62,7 +62,7 @@
|
|||||||
* @brief GFX Graphics Display Basic API
|
* @brief GFX Graphics Display Basic API
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
* @note Also add the specific hardware driver to your makefile.
|
* @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
|
#ifndef GFX_USE_GDISP
|
||||||
#define GFX_USE_GDISP FALSE
|
#define GFX_USE_GDISP FALSE
|
||||||
@ -106,9 +106,9 @@
|
|||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
* @note Also add the specific hardware drivers to your makefile.
|
* @note Also add the specific hardware drivers to your makefile.
|
||||||
* Eg.
|
* Eg.
|
||||||
* include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk
|
* include $(GFXLIB)/drivers/ginput/toggle/Pal/driver.mk
|
||||||
* and...
|
* and...
|
||||||
* include $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld.mk
|
* include $(GFXLIB)/drivers/ginput/touch/MCU/driver.mk
|
||||||
*/
|
*/
|
||||||
#ifndef GFX_USE_GINPUT
|
#ifndef GFX_USE_GINPUT
|
||||||
#define GFX_USE_GINPUT FALSE
|
#define GFX_USE_GINPUT FALSE
|
||||||
@ -121,24 +121,14 @@
|
|||||||
#define GFX_USE_GADC FALSE
|
#define GFX_USE_GADC FALSE
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief GFX Audio Input Device API
|
* @brief GFX Audio API
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
* @note Also add the specific hardware drivers to your makefile.
|
* @note Also add the specific hardware drivers to your makefile.
|
||||||
* Eg.
|
* Eg.
|
||||||
* include $(GFXLIB)/drivers/gaudin/GADC/gaudin_lld.mk
|
* include $(GFXLIB)/drivers/gaudio/GADC/driver.mk
|
||||||
*/
|
*/
|
||||||
#ifndef GFX_USE_GAUDIN
|
#ifndef GFX_USE_GAUDIO
|
||||||
#define GFX_USE_GAUDIN FALSE
|
#define GFX_USE_GAUDIO 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
|
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief GFX Miscellaneous Routines API
|
* @brief GFX Miscellaneous Routines API
|
||||||
@ -173,8 +163,7 @@
|
|||||||
#include "src/gwin/sys_options.h"
|
#include "src/gwin/sys_options.h"
|
||||||
#include "src/ginput/sys_options.h"
|
#include "src/ginput/sys_options.h"
|
||||||
#include "src/gadc/sys_options.h"
|
#include "src/gadc/sys_options.h"
|
||||||
#include "src/gaudin/sys_options.h"
|
#include "src/gaudio/sys_options.h"
|
||||||
#include "src/gaudout/sys_options.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interdependency safety checks on the sub-systems.
|
* Interdependency safety checks on the sub-systems.
|
||||||
@ -187,8 +176,7 @@
|
|||||||
#include "src/gwin/sys_rules.h"
|
#include "src/gwin/sys_rules.h"
|
||||||
#include "src/ginput/sys_rules.h"
|
#include "src/ginput/sys_rules.h"
|
||||||
#include "src/gdisp/sys_rules.h"
|
#include "src/gdisp/sys_rules.h"
|
||||||
#include "src/gaudout/sys_rules.h"
|
#include "src/gaudio/sys_rules.h"
|
||||||
#include "src/gaudin/sys_rules.h"
|
|
||||||
#include "src/gadc/sys_rules.h"
|
#include "src/gadc/sys_rules.h"
|
||||||
#include "src/gevent/sys_rules.h"
|
#include "src/gevent/sys_rules.h"
|
||||||
#include "src/gtimer/sys_rules.h"
|
#include "src/gtimer/sys_rules.h"
|
||||||
@ -210,8 +198,7 @@
|
|||||||
#include "src/gwin/sys_defs.h"
|
#include "src/gwin/sys_defs.h"
|
||||||
#include "src/ginput/sys_defs.h"
|
#include "src/ginput/sys_defs.h"
|
||||||
#include "src/gadc/sys_defs.h"
|
#include "src/gadc/sys_defs.h"
|
||||||
#include "src/gaudin/sys_defs.h"
|
#include "src/gaudio/sys_defs.h"
|
||||||
#include "src/gaudout/sys_defs.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -231,7 +218,7 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* @brief The one call to end it all
|
* @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
|
* @api
|
||||||
*/
|
*/
|
||||||
|
3
gfx.mk
3
gfx.mk
@ -9,7 +9,6 @@ include $(GFXLIB)/src/gtimer/sys_make.mk
|
|||||||
include $(GFXLIB)/src/gwin/sys_make.mk
|
include $(GFXLIB)/src/gwin/sys_make.mk
|
||||||
include $(GFXLIB)/src/ginput/sys_make.mk
|
include $(GFXLIB)/src/ginput/sys_make.mk
|
||||||
include $(GFXLIB)/src/gadc/sys_make.mk
|
include $(GFXLIB)/src/gadc/sys_make.mk
|
||||||
include $(GFXLIB)/src/gaudin/sys_make.mk
|
include $(GFXLIB)/src/gaudio/sys_make.mk
|
||||||
include $(GFXLIB)/src/gaudout/sys_make.mk
|
|
||||||
include $(GFXLIB)/src/gmisc/sys_make.mk
|
include $(GFXLIB)/src/gmisc/sys_make.mk
|
||||||
include $(GFXLIB)/src/gfile/sys_make.mk
|
include $(GFXLIB)/src/gfile/sys_make.mk
|
||||||
|
@ -218,15 +218,11 @@
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// GAUDIN //
|
// GAUDIO //
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
#define GFX_USE_GAUDIN FALSE
|
#define GFX_USE_GAUDIO FALSE
|
||||||
|
#define GAUDIO_NEED_PLAY FALSE
|
||||||
|
#define GAUDIO_NEED_RECORD FALSE
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// GAUDOUT //
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
#define GFX_USE_GAUDOUT FALSE
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@ -243,4 +239,3 @@
|
|||||||
|
|
||||||
|
|
||||||
#endif /* _GFXCONF_H */
|
#endif /* _GFXCONF_H */
|
||||||
|
|
||||||
|
@ -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 */
|
|
||||||
/** @} */
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
GFXSRC += $(GFXLIB)/src/gaudin/gaudin.c
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
@ -6,20 +6,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file src/gaudout/driver.h
|
* @file src/gaudio/driver_play.h
|
||||||
* @brief GAUDOUT - Audio Output driver header file.
|
* @brief GAUDIO - Audio play driver header file.
|
||||||
*
|
*
|
||||||
* @defgroup Driver Driver
|
* @defgroup Driver Driver
|
||||||
* @ingroup GAUDOUT
|
* @ingroup GAUDIO
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _GAUDOUT_LLD_H
|
#ifndef _GAUDIO_PLAY_LLD_H
|
||||||
#define _GAUDOUT_LLD_H
|
#define _GAUDIO_PLAY_LLD_H
|
||||||
|
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
|
|
||||||
#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
|
#if (GFX_USE_GAUDIO && GAUDIO_NEED_PLAY) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Type definitions */
|
/* Type definitions */
|
||||||
@ -37,38 +37,38 @@ extern "C" {
|
|||||||
* @brief Get a block of audio data to play
|
* @brief Get a block of audio data to play
|
||||||
* @return A pointer to the GAaudioData structure or NULL if none is currently available
|
* @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
|
* @iclass
|
||||||
* @notapi
|
* @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.
|
* @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
|
* @iclass
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void gaudoutReleaseDataBlockI(GAudioData *paud);
|
void gaudioPlayReleaseDataBlockI(GAudioData *paud);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Signal that all playing has now stopped
|
* @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
|
* @iclass
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void gaudoutDoneI(void);
|
void gaudioPlayDoneI(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialise the driver
|
* @brief Initialise the play driver
|
||||||
* @return TRUE if the channel and frequency are valid.
|
* @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] channel The channel to use (see the driver for the available channels provided)
|
||||||
* @param[in] frequency The sample frequency to use
|
* @param[in] frequency The sample frequency to use
|
||||||
@ -78,38 +78,30 @@ void gaudoutDoneI(void);
|
|||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start the audio output playing
|
* @brief Start the audio output playing
|
||||||
*
|
*
|
||||||
* @note This may be called at any stage including while the driver
|
* @note This may be called at any stage including while the driver
|
||||||
* is already playing. The driver should check for data blocks
|
* is already playing. The driver should check for data blocks
|
||||||
* to play using @p gaudoutGetDataBlockI().
|
* to play using @p gaudioPlayGetDataBlockI().
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
void gaudout_lld_start(void);
|
void gaudio_play_lld_start(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop the audio output playing.
|
* @brief Stop the audio output playing.
|
||||||
*
|
*
|
||||||
* @note Some drivers may only stop playing at a data block boundary.
|
* @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
|
* @api
|
||||||
*/
|
*/
|
||||||
void gaudout_lld_stop(void);
|
void gaudio_play_lld_stop(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the output volume.
|
* @brief Set the output volume.
|
||||||
@ -122,13 +114,13 @@ void gaudout_lld_stop(void);
|
|||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
bool_t gaudout_lld_set_volume(uint8_t vol);
|
bool_t gaudio_play_lld_set_volume(uint8_t vol);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* GFX_USE_GAUDOUT */
|
#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
|
||||||
|
|
||||||
#endif /* _GAUDOUT_LLD_H */
|
#endif /* _GAUDIO_PLAY_LLD_H */
|
||||||
/** @} */
|
/** @} */
|
108
src/gaudio/driver_record.h
Normal file
108
src/gaudio/driver_record.h
Normal file
@ -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 */
|
||||||
|
/** @} */
|
318
src/gaudio/gaudio.c
Normal file
318
src/gaudio/gaudio.c
Normal file
@ -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 */
|
||||||
|
/** @} */
|
340
src/gaudio/sys_defs.h
Normal file
340
src/gaudio/sys_defs.h
Normal file
@ -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 */
|
||||||
|
/** @} */
|
||||||
|
|
1
src/gaudio/sys_make.mk
Normal file
1
src/gaudio/sys_make.mk
Normal file
@ -0,0 +1 @@
|
|||||||
|
GFXSRC += $(GFXLIB)/src/gaudio/gaudio.c
|
44
src/gaudio/sys_options.h
Normal file
44
src/gaudio/sys_options.h
Normal file
@ -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 */
|
||||||
|
/** @} */
|
54
src/gaudio/sys_rules.h
Normal file
54
src/gaudio/sys_rules.h
Normal file
@ -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 */
|
||||||
|
/** @} */
|
@ -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 */
|
|
||||||
/** @} */
|
|
||||||
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
GFXSRC += $(GFXLIB)/src/gaudout/gaudout.c
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
@ -38,8 +38,7 @@ typedef uint16_t GEventType;
|
|||||||
#define GEVENT_GINPUT_FIRST 0x0100 // GINPUT events range from 0x0100 to 0x01FF
|
#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_GWIN_FIRST 0x0200 // GWIN events range from 0x0200 to 0x02FF
|
||||||
#define GEVENT_GADC_FIRST 0x0300 // GADC events range from 0x0300 to 0x033F
|
#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_GAUDIO_FIRST 0x0340 // GAUDIO events range from 0x0340 to 0x037F
|
||||||
#define GEVENT_GAUDOUT_FIRST 0x0380 // GAUDOUT events range from 0x0380 to 0x03BF
|
|
||||||
#define GEVENT_USER_FIRST 0x8000 // Any application defined events start at 0x8000
|
#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.
|
// This object can be typecast to any GEventXxxxx type to allow any sub-system (or the application) to create events.
|
||||||
|
22
src/gfx.c
22
src/gfx.c
@ -44,13 +44,9 @@ extern void _gosDeinit(void);
|
|||||||
extern void _gadcInit(void);
|
extern void _gadcInit(void);
|
||||||
extern void _gadcDeinit(void);
|
extern void _gadcDeinit(void);
|
||||||
#endif
|
#endif
|
||||||
#if GFX_USE_GAUDIN
|
#if GFX_USE_GAUDIO
|
||||||
extern void _gaudinInit(void);
|
extern void _gaudioInit(void);
|
||||||
extern void _gaudinDeinit(void);
|
extern void _gaudioDeinit(void);
|
||||||
#endif
|
|
||||||
#if GFX_USE_GAUDOUT
|
|
||||||
extern void _gaudoutInit(void);
|
|
||||||
extern void _gaudoutDeinit(void);
|
|
||||||
#endif
|
#endif
|
||||||
#if GFX_USE_GMISC
|
#if GFX_USE_GMISC
|
||||||
extern void _gmiscInit(void);
|
extern void _gmiscInit(void);
|
||||||
@ -88,11 +84,8 @@ void gfxInit(void)
|
|||||||
#if GFX_USE_GADC
|
#if GFX_USE_GADC
|
||||||
_gadcInit();
|
_gadcInit();
|
||||||
#endif
|
#endif
|
||||||
#if GFX_USE_GAUDIN
|
#if GFX_USE_GAUDIO
|
||||||
_gaudinInit();
|
_gaudioInit();
|
||||||
#endif
|
|
||||||
#if GFX_USE_GAUDOUT
|
|
||||||
_gaudoutInit();
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,11 +96,8 @@ void gfxDeinit(void)
|
|||||||
initDone = FALSE;
|
initDone = FALSE;
|
||||||
|
|
||||||
// We deinitialise the opposite way as we initialised
|
// We deinitialise the opposite way as we initialised
|
||||||
#if GFX_USE_GAUDOUT
|
|
||||||
_gaudoutDeinit();
|
|
||||||
#endif
|
|
||||||
#if GFX_USE_GAUDIN
|
#if GFX_USE_GAUDIN
|
||||||
_gaudinDeinit();
|
_gaudioDeinit();
|
||||||
#endif
|
#endif
|
||||||
#if GFX_USE_GADC
|
#if GFX_USE_GADC
|
||||||
_gadcDeinit();
|
_gadcDeinit();
|
||||||
|
Loading…
Reference in New Issue
Block a user