aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gaudio
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-03-11 17:13:31 +1000
committerinmarket <andrewh@inmarket.com.au>2014-03-11 17:13:31 +1000
commitea5a1b849df6e5085a92957ad387f9e653674415 (patch)
tree72ede5ed78263a6fdba25039398b5c2a55bd1d3a /drivers/gaudio
parent944c33cbff5f2cfb1c80f48193aa2161574864fd (diff)
downloaduGFX-ea5a1b849df6e5085a92957ad387f9e653674415.tar.gz
uGFX-ea5a1b849df6e5085a92957ad387f9e653674415.tar.bz2
uGFX-ea5a1b849df6e5085a92957ad387f9e653674415.zip
Combine GAUDIN and GAUDOUT into a single GAUDIO module.
Simplify GAUDIN (now GAUDIO RECORD) api. Update audio demo's to match. Port Win32 driver to new audio api.
Diffstat (limited to 'drivers/gaudio')
-rw-r--r--drivers/gaudio/Win32/driver.mk6
-rw-r--r--drivers/gaudio/Win32/gaudio_play_config.h63
-rw-r--r--drivers/gaudio/Win32/gaudio_play_lld.c185
-rw-r--r--drivers/gaudio/Win32/gaudio_record_config.h63
-rw-r--r--drivers/gaudio/Win32/gaudio_record_lld.c187
-rw-r--r--drivers/gaudio/Win32/readme.txt10
-rw-r--r--drivers/gaudio/gadc/driver.mk5
-rw-r--r--drivers/gaudio/gadc/gaudio_record_board_template.h50
-rw-r--r--drivers/gaudio/gadc/gaudio_record_config.h59
-rw-r--r--drivers/gaudio/gadc/gaudio_record_lld.c62
-rw-r--r--drivers/gaudio/gadc/readme.txt6
11 files changed, 696 insertions, 0 deletions
diff --git a/drivers/gaudio/Win32/driver.mk b/drivers/gaudio/Win32/driver.mk
new file mode 100644
index 00000000..1ea338d5
--- /dev/null
+++ b/drivers/gaudio/Win32/driver.mk
@@ -0,0 +1,6 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gaudio/Win32/gaudio_record_lld.c \
+ $(GFXLIB)/drivers/gaudio/Win32/gaudio_play_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gaudio/Win32
diff --git a/drivers/gaudio/Win32/gaudio_play_config.h b/drivers/gaudio/Win32/gaudio_play_config.h
new file mode 100644
index 00000000..4013e91f
--- /dev/null
+++ b/drivers/gaudio/Win32/gaudio_play_config.h
@@ -0,0 +1,63 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file drivers/gaudio/Win32/gaudio_play_config.h
+ * @brief GAUDIO Play Driver config file.
+ *
+ * @addtogroup GAUDIO
+ * @{
+ */
+
+#ifndef GAUDIO_PLAY_CONFIG_H
+#define GAUDIO_PLAY_CONFIG_H
+
+#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+/**
+ * @brief The maximum sample frequency supported by this audio device
+ */
+#define GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY 44100
+
+/**
+ * @brief The number of audio formats supported by this driver
+ */
+#define GAUDIO_PLAY_NUM_FORMATS 2
+
+/**
+ * @brief The available audio sample formats in order of preference
+ */
+#define GAUDIO_PLAY_FORMAT1 ARRAY_DATA_16BITSIGNED
+#define GAUDIO_PLAY_FORMAT2 ARRAY_DATA_8BITUNSIGNED
+
+/**
+ * @brief The number of audio channels supported by this driver
+ */
+#define GAUDIO_PLAY_NUM_CHANNELS 2
+
+/**
+ * @brief Whether each channel is mono or stereo
+ */
+#define GAUDIO_PLAY_CHANNEL0_IS_STEREO FALSE
+#define GAUDIO_PLAY_CHANNEL1_IS_STEREO TRUE
+
+/**
+ * @brief The list of audio channel names and their uses
+ * @{
+ */
+#define GAUDIO_PLAY_MONO 0
+#define GAUDIO_PLAY_STEREO 1
+/** @} */
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
+
+#endif /* GAUDIO_PLAY_CONFIG_H */
+/** @} */
diff --git a/drivers/gaudio/Win32/gaudio_play_lld.c b/drivers/gaudio/Win32/gaudio_play_lld.c
new file mode 100644
index 00000000..6b4f2dab
--- /dev/null
+++ b/drivers/gaudio/Win32/gaudio_play_lld.c
@@ -0,0 +1,185 @@
+/*
+ * 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_play_lld.c
+ * @brief GAUDIO - Play Driver file for Win32.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY
+
+/* Include the driver defines */
+#include "src/gaudio/driver_play.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 also create higher latency.
+
+static HWAVEOUT 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 waveOutUnPrepareBuffer() which is what we need to use whenever we receive a
+ * MM_WOM_DONE. My callback would need to defer that job to another thread
+ * anyway, so instead just use CALLBACK_THREAD here instead.
+ *************************************************************************/
+
+static bool_t senddata(WAVEHDR *pwh) {
+ GAudioData *paud;
+
+ // Get the next data block to send
+ gfxSystemLock();
+ paud = gaudioPlayGetDataBlockI();
+ if (!paud && !nQueuedBuffers)
+ gaudioPlayDoneI();
+ 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->len;
+ pwh->dwFlags = 0;
+ pwh->dwLoops = 0;
+ if (waveOutPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
+ fprintf(stderr, "GAUDIO: Failed to prepare a play buffer");
+ exit(-1);
+ }
+
+ // Send it to windows
+ if (waveOutWrite(ah, pwh, sizeof(WAVEHDR))) {
+ fprintf(stderr, "GAUDIO: Failed to write the play buffer");
+ exit(-1);
+ }
+
+ nQueuedBuffers++;
+ return TRUE;
+}
+
+static DWORD WINAPI waveProc(LPVOID arg) {
+ MSG msg;
+ WAVEHDR *pwh;
+ (void) arg;
+
+ while (GetMessage(&msg, 0, 0, 0)) {
+ switch (msg.message) {
+ case MM_WOM_DONE:
+ pwh = (WAVEHDR *)msg.lParam;
+
+ // Windows - Let go!
+ waveOutUnprepareHeader(ah, pwh, sizeof(WAVEHDR));
+
+ // Give the buffer back to the Audio Free List
+ gfxSystemLock();
+ gaudioPlayReleaseDataBlockI((GAudioData *)pwh->dwUser);
+ gfxSystemUnlock();
+ pwh->lpData = 0;
+ nQueuedBuffers--;
+
+ // Are we stopping?
+ if (!isRunning) {
+ // Have we finished yet?
+ if (!nQueuedBuffers) {
+ gfxSystemLock();
+ gaudioPlayDoneI();
+ gfxSystemUnlock();
+ }
+ break;
+ }
+
+ // Try and get a new block
+ senddata(pwh);
+ break;
+ }
+ }
+ return 0;
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
+ WAVEFORMATEX wfx;
+
+ if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_16BITSIGNED)
+ return FALSE;
+
+ if (!waveThread) {
+ if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
+ fprintf(stderr, "GAUDIO: Can't create WAVE play-back thread\n");
+ exit(-1);
+ }
+ CloseHandle(waveThread);
+ }
+
+ wfx.wFormatTag = WAVE_FORMAT_PCM;
+ wfx.nChannels = channel == GAUDIO_PLAY_STEREO ? 2 : 1;
+ wfx.nSamplesPerSec = frequency;
+ wfx.nBlockAlign = wfx.nChannels * (format == ARRAY_DATA_8BITUNSIGNED ? 1 : 2);
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+ wfx.wBitsPerSample = (format == ARRAY_DATA_8BITUNSIGNED ? 8 : 16);
+ wfx.cbSize = 0;
+
+ if (ah) {
+ waveOutClose(ah);
+ ah = 0;
+ }
+ if (waveOutOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
+ fprintf(stderr, "GAUDIO: Can't open WAVE play-back device\n");
+ exit(-1);
+ }
+
+ return TRUE;
+}
+
+bool_t gaudio_play_lld_set_volume(uint8_t vol) {
+ if (!ah)
+ return FALSE;
+ return waveOutSetVolume(ah, (((uint16_t)vol)<<8)|vol) != 0;
+}
+
+void gaudio_play_lld_start(void) {
+ WAVEHDR *pwh;
+
+ isRunning = TRUE;
+ 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 Audio Out Queue
+ if (!senddata(pwh))
+ break;
+ }
+}
+
+void gaudio_play_lld_stop(void) {
+ isRunning = FALSE;
+ waveOutReset(ah);
+ while(nQueuedBuffers) Sleep(1);
+}
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
diff --git a/drivers/gaudio/Win32/gaudio_record_config.h b/drivers/gaudio/Win32/gaudio_record_config.h
new file mode 100644
index 00000000..4d952e1d
--- /dev/null
+++ b/drivers/gaudio/Win32/gaudio_record_config.h
@@ -0,0 +1,63 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file drivers/gaudio/Win32/gaudio_record_config.h
+ * @brief GAUDIO Record Driver config file.
+ *
+ * @addtogroup GAUDIO
+ * @{
+ */
+
+#ifndef GAUDIO_RECORD_CONFIG_H
+#define GAUDIO_RECORD_CONFIG_H
+
+#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+/**
+ * @brief The maximum sample frequency supported by this audio device
+ */
+#define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY 44100
+
+/**
+ * @brief The number of audio formats supported by this driver
+ */
+#define GAUDIO_RECORD_NUM_FORMATS 2
+
+/**
+ * @brief The available audio sample formats in order of preference
+ */
+#define GAUDIO_RECORD_FORMAT1 ARRAY_DATA_16BITSIGNED
+#define GAUDIO_RECORD_FORMAT2 ARRAY_DATA_8BITUNSIGNED
+
+/**
+ * @brief The number of audio channels supported by this driver
+ */
+#define GAUDIO_RECORD_NUM_CHANNELS 2
+
+/**
+ * @brief Whether each channel is mono or stereo
+ */
+#define GAUDIO_RECORD_CHANNEL0_IS_STEREO FALSE
+#define GAUDIO_RECORD_CHANNEL1_IS_STEREO TRUE
+
+/**
+ * @brief The list of audio channels and their uses
+ * @{
+ */
+#define GAUDIO_RECORD_MONO 0
+#define GAUDIO_RECORD_STEREO 1
+/** @} */
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
+
+#endif /* GAUDIO_RECORD_CONFIG_H */
+/** @} */
diff --git a/drivers/gaudio/Win32/gaudio_record_lld.c b/drivers/gaudio/Win32/gaudio_record_lld.c
new file mode 100644
index 00000000..259707e3
--- /dev/null
+++ b/drivers/gaudio/Win32/gaudio_record_lld.c
@@ -0,0 +1,187 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file drivers/gaudio/Win32/gaudio_record_lld.c
+ * @brief GAUDIO - Record Driver file for Win32.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
+
+/* Include the driver defines */
+#include "src/gaudio/driver_record.h"
+
+#undef Red
+#undef Green
+#undef Blue
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <stdio.h>
+#include <mmsystem.h>
+
+#define MAX_WAVE_HEADERS 2 // Larger numbers enable more buffering which is good for ensuring
+ // there are no skips due to data not being available, however larger
+ // numbers of buffers chews buffers on the free-list.
+
+static HWAVEIN ah = 0;
+static volatile int nQueuedBuffers;
+static bool_t isRunning;
+static WAVEHDR WaveHdrs[MAX_WAVE_HEADERS];
+static HANDLE waveThread;
+static DWORD threadID;
+
+/**************************** waveProc() *******************************
+ * We don't use CALLBACK_FUNCTION because it is restricted to calling only
+ * a few particular Windows functions, namely some of the time functions,
+ * and a few of the Low Level MIDI API. If you violate this rule, your app can
+ * hang inside of the callback). One of the Windows API that a callback can't
+ * call is waveInAddBuffer() which is what we need to use whenever we receive a
+ * MM_WIM_DATA. My callback would need to defer that job to another thread
+ * anyway, so instead just use CALLBACK_THREAD here instead.
+ *************************************************************************/
+
+static bool_t getbuffer(WAVEHDR *pwh) {
+ GAudioData *paud;
+
+ // Get the next data block to send
+ gfxSystemLock();
+ paud = gaudioRecordGetFreeBlockI();
+ if (!paud && !nQueuedBuffers)
+ gaudioRecordDoneI();
+ gfxSystemUnlock();
+ if (!paud)
+ return FALSE;
+
+ // Prepare the wave header for Windows
+ pwh->dwUser = (DWORD_PTR)paud;
+ pwh->lpData = (LPSTR)(paud+1); // The data is on the end of the structure
+ pwh->dwBufferLength = paud->size;
+ pwh->dwFlags = 0;
+ if (waveInPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
+ fprintf(stderr, "GAUDIO: Failed to prepare a record buffer");
+ exit(-1);
+ }
+
+ // Send it to windows
+ if (waveInAddBuffer(ah, pwh, sizeof(WAVEHDR))) {
+ fprintf(stderr, "GAUDIO: Failed to add the record buffer");
+ exit(-1);
+ }
+
+ nQueuedBuffers++;
+ return TRUE;
+}
+
+static DWORD WINAPI waveProc(LPVOID arg) {
+ MSG msg;
+ WAVEHDR *pwh;
+ GAudioData *paud;
+ (void) arg;
+
+ while (GetMessage(&msg, 0, 0, 0)) {
+ switch (msg.message) {
+ case MM_WIM_DATA:
+ pwh = (WAVEHDR *)msg.lParam;
+
+ // Windows - Let go!
+ waveInUnprepareHeader(ah, pwh, sizeof(WAVEHDR));
+
+ // Save the buffer in the audio record list
+ paud = (GAudioData *)pwh->dwUser;
+ paud->len = pwh->dwBytesRecorded;
+ gfxSystemLock();
+ gaudioRecordSaveDataBlockI(paud);
+ gfxSystemUnlock();
+ pwh->lpData = 0;
+ nQueuedBuffers--;
+
+ // Are we stopping?
+ if (!isRunning) {
+ // Have we finished yet?
+ if (!nQueuedBuffers) {
+ gfxSystemLock();
+ gaudioRecordDoneI();
+ gfxSystemUnlock();
+ }
+ break;
+ }
+
+ // Try and get a new block
+ getbuffer(pwh);
+ break;
+ }
+ }
+ return 0;
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+bool_t gaudio_record_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
+ WAVEFORMATEX wfx;
+
+ if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_16BITSIGNED)
+ return FALSE;
+
+ if (!waveThread) {
+ if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
+ fprintf(stderr, "GAUDIO: Can't create WAVE recording thread\n");
+ exit(-1);
+ }
+ CloseHandle(waveThread);
+ }
+
+ wfx.wFormatTag = WAVE_FORMAT_PCM;
+ wfx.nChannels = channel == GAUDIO_RECORD_STEREO ? 2 : 1;
+ wfx.nSamplesPerSec = frequency;
+ wfx.nBlockAlign = wfx.nChannels * (format == ARRAY_DATA_8BITUNSIGNED ? 1 : 2);
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+ wfx.wBitsPerSample = (format == ARRAY_DATA_8BITUNSIGNED ? 8 : 16);
+ wfx.cbSize = 0;
+
+ if (ah) {
+ waveInClose(ah);
+ ah = 0;
+ }
+ if (waveInOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
+ fprintf(stderr, "GAUDIN: Can't open WAVE recording device\n");
+ exit(-1);
+ }
+
+ return TRUE;
+}
+
+void gaudio_record_lld_start(void) {
+ WAVEHDR *pwh;
+
+ if (!ah)
+ return;
+
+ while (nQueuedBuffers < MAX_WAVE_HEADERS) {
+ // Find the empty one - there will always be at least one.
+ for(pwh = WaveHdrs; pwh->lpData; pwh++);
+
+ // Grab the next audio block from the free-list
+ if (!getbuffer(pwh))
+ break;
+ }
+ if (!isRunning) {
+ isRunning = TRUE;
+ waveInStart(ah);
+ }
+}
+
+void gaudio_record_lld_stop(void) {
+ isRunning = FALSE;
+ waveInReset(ah);
+ while(nQueuedBuffers) Sleep(1);
+}
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
diff --git a/drivers/gaudio/Win32/readme.txt b/drivers/gaudio/Win32/readme.txt
new file mode 100644
index 00000000..83cb9c33
--- /dev/null
+++ b/drivers/gaudio/Win32/readme.txt
@@ -0,0 +1,10 @@
+This driver uses the Win32 audio system to provide GAUDIO play and record channels.
+
+For PLAY - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
+For RECORD - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
+
+For stereo, the samples are interleaved. Remember to allocate enough space for two samples per
+sample period.
+
+This is a simple driver that makes no changes to the mixer so set up the audio mixer using
+the windows control panel audio mixer before starting recording/playback.
diff --git a/drivers/gaudio/gadc/driver.mk b/drivers/gaudio/gadc/driver.mk
new file mode 100644
index 00000000..4d79da25
--- /dev/null
+++ b/drivers/gaudio/gadc/driver.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gaudio/gadc/gaudio_record_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gaudio/gadc
diff --git a/drivers/gaudio/gadc/gaudio_record_board_template.h b/drivers/gaudio/gadc/gaudio_record_board_template.h
new file mode 100644
index 00000000..26e87d88
--- /dev/null
+++ b/drivers/gaudio/gadc/gaudio_record_board_template.h
@@ -0,0 +1,50 @@
+/*
+ * 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/gadc/gaudio_record_board_template.h
+ * @brief GAUDIO Record Driver board config board file
+ *
+ * @addtogroup GAUDIO
+ * @{
+ */
+
+#ifndef _GAUDIO_RECORD_BOARD_H
+#define _GAUDIO_RECORD_BOARD_H
+
+/*===========================================================================*/
+/* Audio inputs on this board */
+/*===========================================================================*/
+
+/**
+ * @brief The number of audio channels supported by this driver
+ * @note This is an example
+ */
+#define GAUDIO_RECORD_NUM_CHANNELS 1
+
+/**
+ * @brief The list of audio channels and their uses
+ * @note This is an example
+ * @{
+ */
+#define GAUDIO_RECORD_MICROPHONE 0
+/** @} */
+
+/**
+ * @brief The audio channel to GADC physical device assignment
+ * @note This is an example
+ * @{
+ */
+#ifdef GAUDIO_RECORD_LLD_IMPLEMENTATION
+ static uint32_t gaudin_lld_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = {
+ GADC_PHYSDEV_MICROPHONE,
+ };
+#endif
+/** @} */
+
+#endif /* _GAUDIO_RECORD_BOARD_H */
+/** @} */
diff --git a/drivers/gaudio/gadc/gaudio_record_config.h b/drivers/gaudio/gadc/gaudio_record_config.h
new file mode 100644
index 00000000..22d8750f
--- /dev/null
+++ b/drivers/gaudio/gadc/gaudio_record_config.h
@@ -0,0 +1,59 @@
+/*
+ * 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/gadc/gaudio_record_config.h
+ * @brief GAUDIN 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 audio record sample type
+ * @details For this driver it matches the cpu sample type
+ */
+typedef adcsample_t audio_record_sample_t;
+
+/**
+ * @brief The maximum sample frequency supported by this audio device
+ * @details For this driver it matches the GADC maximum high speed sample rate
+ */
+#define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY GADC_MAX_HIGH_SPEED_SAMPLERATE
+
+/**
+ * @brief The number of bits in a sample
+ * @details For this driver it matches the cpu sample bits
+ */
+#define GAUDIO_RECORD_BITS_PER_SAMPLE GADC_BITS_PER_SAMPLE
+
+/**
+ * @brief The format of an audio sample
+ * @details For this driver it matches the cpu sample format
+ */
+#define GAUDIO_RECORD_SAMPLE_FORMAT GADC_SAMPLE_FORMAT
+
+/**
+ * For the GAUDIO driver that uses GADC - all the remaining config definitions are specific
+ * to the board.
+ */
+/* Include the user supplied board definitions */
+#include "gaudio_record_board.h"
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
+
+#endif /* GAUDIO_RECORD_CONFIG_H */
+/** @} */
diff --git a/drivers/gaudio/gadc/gaudio_record_lld.c b/drivers/gaudio/gadc/gaudio_record_lld.c
new file mode 100644
index 00000000..ee994dc1
--- /dev/null
+++ b/drivers/gaudio/gadc/gaudio_record_lld.c
@@ -0,0 +1,62 @@
+/*
+ * 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/gadc/gaudio_record_lld.c
+ * @brief GAUDIO - Record Driver file for using the cpu ADC (via GADC).
+ *
+ * @addtogroup GAUDIO
+ *
+ * @{
+ */
+
+/**
+ * We are now implementing the driver - pull in our channel table
+ * from the board definitions.
+ */
+#define GAUDIO_RECORD_IMPLEMENTATION
+
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
+
+/* Double check the GADC system is turned on */
+#if !GFX_USE_GADC
+ #error "GAUDIO - The GADC driver for GAUDIO requires GFX_USE_GADC to be TRUE"
+#endif
+
+/* Include the driver defines */
+#include "src/gaudio/driver_record.h"
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+void gaudin_lld_init(const gaudin_params *paud) {
+ /* Setup the high speed GADC */
+ gadcHighSpeedInit(gaudin_lld_physdevs[paud->channel], paud->frequency, paud->buffer, paud->bufcount, paud->samplesPerEvent);
+
+ /* Register ourselves for ISR callbacks */
+ gadcHighSpeedSetISRCallback(GAUDIN_ISR_CompleteI);
+
+ /**
+ * The gadc driver handles any errors for us by restarting the transaction so there is
+ * no need for us to setup anything for GAUDIN_ISR_ErrorI()
+ */
+}
+
+void gaudin_lld_start(void) {
+ gadcHighSpeedStart();
+}
+
+void gaudin_lld_stop(void) {
+ gadcHighSpeedStop();
+}
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
+/** @} */
diff --git a/drivers/gaudio/gadc/readme.txt b/drivers/gaudio/gadc/readme.txt
new file mode 100644
index 00000000..47d3f191
--- /dev/null
+++ b/drivers/gaudio/gadc/readme.txt
@@ -0,0 +1,6 @@
+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.
+
+For stereo, the samples are interleaved. Remember to allocate enough space for two samples per
+sample period.