aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/audio/Win32/driver.mk6
-rw-r--r--drivers/audio/Win32/gaudin_lld.c (renamed from drivers/gaudin/Win32/gaudin_lld.c)86
-rw-r--r--drivers/audio/Win32/gaudin_lld_config.h (renamed from drivers/gaudin/Win32/gaudin_lld_config.h)2
-rw-r--r--drivers/audio/Win32/gaudout_lld.c190
-rw-r--r--drivers/audio/Win32/gaudout_lld_config.h64
-rw-r--r--drivers/audio/Win32/readme.txt10
-rw-r--r--drivers/audio/gadc/driver.mk (renamed from drivers/gaudin/gadc/gaudin_lld.mk)2
-rw-r--r--drivers/audio/gadc/gaudin_lld.c (renamed from drivers/gaudin/gadc/gaudin_lld.c)4
-rw-r--r--drivers/audio/gadc/gaudin_lld_board_template.h (renamed from drivers/gaudin/gadc/gaudin_lld_board_template.h)0
-rw-r--r--drivers/audio/gadc/gaudin_lld_config.h (renamed from drivers/gaudin/gadc/gaudin_lld_config.h)0
-rw-r--r--drivers/audio/gadc/readme.txt6
-rw-r--r--drivers/gaudin/Win32/gaudin_lld.mk5
-rw-r--r--drivers/gaudin/Win32/readme.txt9
-rw-r--r--drivers/multiple/Win32/driver.mk (renamed from drivers/multiple/Win32/gdisp_lld.mk)4
14 files changed, 321 insertions, 67 deletions
diff --git a/drivers/audio/Win32/driver.mk b/drivers/audio/Win32/driver.mk
new file mode 100644
index 00000000..6f4ef084
--- /dev/null
+++ b/drivers/audio/Win32/driver.mk
@@ -0,0 +1,6 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/audio/Win32/gaudin_lld.c \
+ $(GFXLIB)/drivers/audio/Win32/gaudout_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/audio/Win32
diff --git a/drivers/gaudin/Win32/gaudin_lld.c b/drivers/audio/Win32/gaudin_lld.c
index e798f4ef..2c8431cf 100644
--- a/drivers/gaudin/Win32/gaudin_lld.c
+++ b/drivers/audio/Win32/gaudin_lld.c
@@ -6,7 +6,7 @@
*/
/**
- * @file drivers/gaudin/Win32/gaudin_lld.c
+ * @file drivers/audio/Win32/gaudin_lld.c
* @brief GAUDIN - Driver file for Win32.
*/
@@ -26,9 +26,10 @@
#include <mmsystem.h>
static HWAVEIN ah;
-static volatile int nUsedBuffers;
+static volatile int nQueuedBuffers;
+static bool_t isClosing;
static WAVEHDR *pWaveHdrs;
-static HANDLE waveInThread;
+static HANDLE waveThread;
static DWORD threadID;
/*
@@ -45,7 +46,7 @@ static void PrintWaveErrorMsg(DWORD err, TCHAR * str)
}
*/
-/**************************** waveInProc() *******************************
+/**************************** 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
@@ -55,43 +56,32 @@ static void PrintWaveErrorMsg(DWORD err, TCHAR * str)
* anyway, so instead just use CALLBACK_THREAD here instead.
*************************************************************************/
-DWORD WINAPI waveInProc(LPVOID arg) {
+static DWORD WINAPI waveProc(LPVOID arg) {
MSG msg;
- bool_t isRecording;
(void) arg;
- isRecording = FALSE;
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 still recording? */
- if (isRecording) {
- /* Yes. Now we need to requeue this buffer so the driver can use it for another block of audio
+ /* 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));
-
- } else {
- /* We aren't recording, so another WAVEHDR has been returned to us after recording has stopped.
- * When we get all of them back, DoneAll will be equal to how many WAVEHDRs we queued
- */
- nUsedBuffers--;
- waveInUnprepareHeader(ah, (WAVEHDR *)msg.lParam, sizeof(WAVEHDR));
}
break;
-
- case MM_WIM_OPEN:
- isRecording = TRUE;
- break;
-
- case MM_WIM_CLOSE:
- isRecording = FALSE;
- break;
}
}
return 0;
@@ -101,12 +91,20 @@ DWORD WINAPI waveInProc(LPVOID arg) {
/* 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) {
-// uint16_t channel;
-// uint32_t frequency;
-// audin_sample_t *buffer;
-// size_t bufcount;
-// size_t samplesPerEvent;
WAVEFORMATEX wfx;
size_t spaceleft;
audin_sample_t *p;
@@ -114,15 +112,15 @@ void gaudin_lld_init(const gaudin_params *paud) {
size_t nBuffers;
size_t sz;
- if (!waveInThread) {
- if (!(waveInThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveInProc, 0, 0, &threadID))) {
- fprintf(stderr, "GAUDIN: Can't create WAVE recording thread\n");
+ 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(waveInThread);
+ CloseHandle(waveThread);
}
- nUsedBuffers = 0;
+ gaudin_lld_deinit();
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = paud->channel == GAUDIN_STEREO ? 2 : 1;
@@ -153,26 +151,20 @@ void gaudin_lld_init(const gaudin_params *paud) {
phdr->dwFlags = 0;
if (!waveInPrepareHeader(ah, phdr, sizeof(WAVEHDR))
&& !waveInAddBuffer(ah, phdr, sizeof(WAVEHDR)))
- nUsedBuffers++;
+ nQueuedBuffers++;
else
fprintf(stderr, "GAUDIN: Buffer prepare failed\n");
}
- if (!nUsedBuffers)
+ if (!nQueuedBuffers)
fprintf(stderr, "GAUDIN: Failed to prepare any buffers\n");
}
-void gadc_lld_start(void) {
- if (nUsedBuffers)
- waveInStart(ah);
+void gaudin_lld_start(void) {
+ waveInStart(ah);
}
-void gadc_lld_stop(void) {
- waveInReset(ah);
- while(nUsedBuffers) Sleep(1);
- if (pWaveHdrs) {
- gfxFree(pWaveHdrs);
- pWaveHdrs = 0;
- }
+void gaudin_lld_stop(void) {
+ waveInStop(ah);
}
#endif /* GFX_USE_GAUDIN */
diff --git a/drivers/gaudin/Win32/gaudin_lld_config.h b/drivers/audio/Win32/gaudin_lld_config.h
index 804d2fc4..78ddffaa 100644
--- a/drivers/gaudin/Win32/gaudin_lld_config.h
+++ b/drivers/audio/Win32/gaudin_lld_config.h
@@ -6,7 +6,7 @@
*/
/**
- * @file drivers/multiple/Win32/gaudin_lld_config.h
+ * @file drivers/audio/Win32/gaudin_lld_config.h
* @brief GAUDIN Driver config file.
*
* @addtogroup GAUDIN
diff --git a/drivers/audio/Win32/gaudout_lld.c b/drivers/audio/Win32/gaudout_lld.c
new file mode 100644
index 00000000..9581fa45
--- /dev/null
+++ b/drivers/audio/Win32/gaudout_lld.c
@@ -0,0 +1,190 @@
+/*
+ * 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/gaudout_lld.c
+ * @brief GAUDOUT - Driver file for Win32.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDOUT
+
+/* Include the driver defines */
+#include "src/gaudout/driver.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;
+
+/*
+static void PrintWaveErrorMsg(DWORD err, TCHAR * str)
+{
+ #define BUFFERSIZE 128
+ char buffer[BUFFERSIZE];
+
+ fprintf(stderr, "GAUDOUT: ERROR 0x%08X: %s\r\n", err, str);
+ if (mciGetErrorString(err, &buffer[0], sizeof(buffer)))
+ fprintf(stderr, "%s\r\n", &buffer[0]);
+ else
+ fprintf(stderr, "0x%08X returned!\r\n", err);
+}
+*/
+
+/**************************** waveProc() *******************************
+ * We don't use CALLBACK_FUNCTION because it is restricted to calling only
+ * a few particular Windows functions, namely some of the time functions,
+ * 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
+ if (!(paud = gaudoutGetDataBlockI()))
+ 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))) {
+ pwh->lpData = 0;
+ fprintf(stderr, "GAUDOUT: Failed to prepare a buffer");
+ return FALSE;
+ }
+
+ // Send it to windows
+ if (waveOutWrite(ah, pwh, sizeof(WAVEHDR))) {
+ pwh->lpData = 0;
+ fprintf(stderr, "GAUDOUT: Failed to write the buffer");
+ return FALSE;
+ }
+
+ 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
+ gaudoutReleaseDataBlockI((GAudioData *)pwh->dwUser);
+ pwh->lpData = 0;
+ nQueuedBuffers--;
+
+ // Try and get a new block
+ if (isRunning)
+ senddata(pwh);
+ break;
+ }
+ }
+ return 0;
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+void gaudout_lld_deinit() {
+ if (ah) {
+ isRunning = FALSE;
+ waveOutReset(ah);
+ while(nQueuedBuffers) Sleep(1);
+ waveOutClose(ah);
+ ah = 0;
+ }
+}
+
+bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency) {
+ WAVEFORMATEX wfx;
+
+ if (!waveThread) {
+ if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
+ fprintf(stderr, "GAUDOUT: Can't create WAVE play-back thread\n");
+ return FALSE;
+ }
+ CloseHandle(waveThread);
+ }
+
+ wfx.wFormatTag = WAVE_FORMAT_PCM;
+ wfx.nChannels = channel == GAUDOUT_STEREO ? 2 : 1;
+ wfx.nSamplesPerSec = frequency;
+ wfx.nBlockAlign = wfx.nChannels * sizeof(audout_sample_t);
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+ wfx.wBitsPerSample = sizeof(audout_sample_t) * 8;
+ wfx.cbSize = 0;
+
+ if (waveOutOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
+ fprintf(stderr, "GAUDOUT: Can't open WAVE play-back device\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+bool_t gaudout_lld_set_volume(uint8_t vol) {
+ if (!ah)
+ return FALSE;
+ return waveOutSetVolume(ah, (((uint16_t)vol)<<8)|vol) != 0;
+}
+
+void gaudout_lld_start(void) {
+ WAVEHDR *pwh;
+
+ if (!ah)
+ return;
+
+ isRunning = TRUE;
+ while (nQueuedBuffers < MAX_WAVE_HEADERS) {
+ // Find the empty one - there will always be at least one.
+ for(pwh = WaveHdrs; pwh->lpData; pwh++);
+
+ // Grab the next audio block from the Audio Out Queue
+ if (!senddata(pwh))
+ break;
+ }
+}
+
+void gaudout_lld_stop(void) {
+ isRunning = FALSE;
+ if (ah)
+ waveOutReset(ah);
+}
+
+#endif /* GFX_USE_GAUDOUT */
diff --git a/drivers/audio/Win32/gaudout_lld_config.h b/drivers/audio/Win32/gaudout_lld_config.h
new file mode 100644
index 00000000..157f33f0
--- /dev/null
+++ b/drivers/audio/Win32/gaudout_lld_config.h
@@ -0,0 +1,64 @@
+/*
+ * 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/gaudout_lld_config.h
+ * @brief GAUDOUT Driver config file.
+ *
+ * @addtogroup GAUDOUT
+ * @{
+ */
+
+#ifndef GAUDOUT_LLD_CONFIG_H
+#define GAUDIN_LLD_CONFIG_H
+
+#if GFX_USE_GAUDOUT
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+/**
+ * @brief The audio input sample type
+ */
+//typedef uint8_t audout_sample_t;
+typedef int16_t audout_sample_t;
+
+/**
+ * @brief The maximum sample frequency supported by this audio device
+ */
+#define GAUDOUT_MAX_SAMPLE_FREQUENCY 44100
+
+/**
+ * @brief The number of bits in a sample
+ */
+//#define GAUDOUT_BITS_PER_SAMPLE 8
+#define GAUDOUT_BITS_PER_SAMPLE 16
+
+/**
+ * @brief The format of an audio sample
+ */
+//#define GAUDOUT_SAMPLE_FORMAT ARRAY_DATA_8BITUNSIGNED
+#define GAUDOUT_SAMPLE_FORMAT ARRAY_DATA_16BITSIGNED
+
+/**
+ * @brief The number of audio channels supported by this driver
+ */
+#define GAUDOUT_NUM_CHANNELS 2
+
+/**
+ * @brief The list of audio channels and their uses
+ * @{
+ */
+#define GAUDOUT_MONO 0
+#define GAUDOUT_STEREO 1
+/** @} */
+
+#endif /* GFX_USE_GAUDOUT */
+
+#endif /* GAUDOUT_LLD_CONFIG_H */
+/** @} */
diff --git a/drivers/audio/Win32/readme.txt b/drivers/audio/Win32/readme.txt
new file mode 100644
index 00000000..784f0a89
--- /dev/null
+++ b/drivers/audio/Win32/readme.txt
@@ -0,0 +1,10 @@
+This driver uses the Win32 audio system to provide GAUDIN and GAUDOUT channels.
+
+For GAUDIN - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
+For GAUDOUT - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
+
+For stereo, the samples are interleaved. Remember to allocate enough space for two samples per
+sample period.
+
+This is a simple driver that makes no changes to the mixer so set up the audio mixer using
+the windows control panel audio mixer before starting recording/playback.
diff --git a/drivers/gaudin/gadc/gaudin_lld.mk b/drivers/audio/gadc/driver.mk
index c969e80b..b991ede8 100644
--- a/drivers/gaudin/gadc/gaudin_lld.mk
+++ b/drivers/audio/gadc/driver.mk
@@ -2,4 +2,4 @@
GFXSRC += $(GFXLIB)/drivers/gaudin/gadc/gaudin_lld.c
# Required include directories
-GFXINC += $(GFXLIB)/drivers/gaudin/gadc
+GFXINC += $(GFXLIB)/drivers/audio/gadc
diff --git a/drivers/gaudin/gadc/gaudin_lld.c b/drivers/audio/gadc/gaudin_lld.c
index 972f3dcf..002d9e9b 100644
--- a/drivers/gaudin/gadc/gaudin_lld.c
+++ b/drivers/audio/gadc/gaudin_lld.c
@@ -50,11 +50,11 @@ void gaudin_lld_init(const gaudin_params *paud) {
*/
}
-void gadc_lld_start(void) {
+void gaudin_lld_start(void) {
gadcHighSpeedStart();
}
-void gadc_lld_stop(void) {
+void gaudin_lld_stop(void) {
gadcHighSpeedStop();
}
diff --git a/drivers/gaudin/gadc/gaudin_lld_board_template.h b/drivers/audio/gadc/gaudin_lld_board_template.h
index 89cc0c12..89cc0c12 100644
--- a/drivers/gaudin/gadc/gaudin_lld_board_template.h
+++ b/drivers/audio/gadc/gaudin_lld_board_template.h
diff --git a/drivers/gaudin/gadc/gaudin_lld_config.h b/drivers/audio/gadc/gaudin_lld_config.h
index a9fd02ae..a9fd02ae 100644
--- a/drivers/gaudin/gadc/gaudin_lld_config.h
+++ b/drivers/audio/gadc/gaudin_lld_config.h
diff --git a/drivers/audio/gadc/readme.txt b/drivers/audio/gadc/readme.txt
new file mode 100644
index 00000000..1d3877e8
--- /dev/null
+++ b/drivers/audio/gadc/readme.txt
@@ -0,0 +1,6 @@
+This driver uses the generic GADC driver to provide a GAUDIN 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.
diff --git a/drivers/gaudin/Win32/gaudin_lld.mk b/drivers/gaudin/Win32/gaudin_lld.mk
deleted file mode 100644
index 3a822971..00000000
--- a/drivers/gaudin/Win32/gaudin_lld.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gaudin/Win32/gaudin_lld.c
-
-# Required include directories
-GFXINC += $(GFXLIB)/drivers/gaudin/Win32
diff --git a/drivers/gaudin/Win32/readme.txt b/drivers/gaudin/Win32/readme.txt
deleted file mode 100644
index b921c5e5..00000000
--- a/drivers/gaudin/Win32/readme.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-This driver uses the Win32 audio system to provide a GAUDIN channel.
-
-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 (obviously in record mode) before starting recording.
diff --git a/drivers/multiple/Win32/gdisp_lld.mk b/drivers/multiple/Win32/driver.mk
index f9242380..d9654dfe 100644
--- a/drivers/multiple/Win32/gdisp_lld.mk
+++ b/drivers/multiple/Win32/driver.mk
@@ -1,2 +1,2 @@
-GFXINC += $(GFXLIB)/drivers/multiple/Win32
-GFXSRC += $(GFXLIB)/drivers/multiple/Win32/gdisp_lld_Win32.c
+GFXINC += $(GFXLIB)/drivers/multiple/Win32
+GFXSRC += $(GFXLIB)/drivers/multiple/Win32/gdisp_lld_Win32.c