aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gaudin/Win32
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2013-12-22 21:38:57 +1000
committerinmarket <andrewh@inmarket.com.au>2013-12-22 21:38:57 +1000
commitd8bde70ab6bdf8d05d84e1a0622e39d65b5ae895 (patch)
tree3d450c637e8c2cbcaa923e470545ae955d126196 /drivers/gaudin/Win32
parentf8772b1b04fe1e2bac3405eabc98794ddd01f746 (diff)
downloaduGFX-d8bde70ab6bdf8d05d84e1a0622e39d65b5ae895.tar.gz
uGFX-d8bde70ab6bdf8d05d84e1a0622e39d65b5ae895.tar.bz2
uGFX-d8bde70ab6bdf8d05d84e1a0622e39d65b5ae895.zip
Add Win32 GAUDIN driver.
Diffstat (limited to 'drivers/gaudin/Win32')
-rw-r--r--drivers/gaudin/Win32/gaudin_lld.c178
-rw-r--r--drivers/gaudin/Win32/gaudin_lld.mk5
-rw-r--r--drivers/gaudin/Win32/gaudin_lld_config.h64
3 files changed, 247 insertions, 0 deletions
diff --git a/drivers/gaudin/Win32/gaudin_lld.c b/drivers/gaudin/Win32/gaudin_lld.c
new file mode 100644
index 00000000..665c89f7
--- /dev/null
+++ b/drivers/gaudin/Win32/gaudin_lld.c
@@ -0,0 +1,178 @@
+/*
+ * 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/gaudin/Win32/gaudin_lld.c
+ * @brief GAUDIN - Driver file for Win32.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDIN
+
+/* Include the driver defines */
+#include "gaudin/lld/gaudin_lld.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 nUsedBuffers;
+static WAVEHDR *pWaveHdrs;
+static HANDLE waveInThread;
+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);
+}
+*/
+
+/**************************** waveInProc() *******************************
+ * 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.
+ *************************************************************************/
+
+DWORD WINAPI waveInProc(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
+ * 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;
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+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;
+ WAVEHDR *phdr;
+ 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");
+ return;
+ }
+ CloseHandle(waveInThread);
+ }
+
+ nUsedBuffers = 0;
+
+ 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 = (WAVEHDR *)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)))
+ nUsedBuffers++;
+ else
+ fprintf(stderr, "GAUDIN: Buffer prepare failed\n");
+ }
+ if (!nUsedBuffers)
+ fprintf(stderr, "GAUDIN: Failed to prepare any buffers\n");
+}
+
+void gadc_lld_start(void) {
+ if (nUsedBuffers)
+ waveInStart(ah);
+}
+
+void gadc_lld_stop(void) {
+ waveInReset(ah);
+ while(nUsedBuffers) Sleep(1);
+ if (pWaveHdrs) {
+ gfxFree(pWaveHdrs);
+ pWaveHdrs = 0;
+ }
+}
+
+#endif /* GFX_USE_GAUDIN */
diff --git a/drivers/gaudin/Win32/gaudin_lld.mk b/drivers/gaudin/Win32/gaudin_lld.mk
new file mode 100644
index 00000000..3a822971
--- /dev/null
+++ b/drivers/gaudin/Win32/gaudin_lld.mk
@@ -0,0 +1,5 @@
+# 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/gaudin_lld_config.h b/drivers/gaudin/Win32/gaudin_lld_config.h
new file mode 100644
index 00000000..804d2fc4
--- /dev/null
+++ b/drivers/gaudin/Win32/gaudin_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/multiple/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 */
+/** @} */