aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gaudio
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-03-30 19:10:31 +1000
committerinmarket <andrewh@inmarket.com.au>2014-03-30 19:10:31 +1000
commit04f03ea71da1337c501b598c6038afaf0216fed8 (patch)
tree7d31e7b75256f42bc6b98bce7e625431d4f7722a /drivers/gaudio
parentc16cb15ce9b5e4cc1a913def9614f8a587bc0868 (diff)
downloaduGFX-04f03ea71da1337c501b598c6038afaf0216fed8.tar.gz
uGFX-04f03ea71da1337c501b598c6038afaf0216fed8.tar.bz2
uGFX-04f03ea71da1337c501b598c6038afaf0216fed8.zip
New PWM audio driver for audio output using a digital pin on a CPU
Diffstat (limited to 'drivers/gaudio')
-rw-r--r--drivers/gaudio/pwm/driver.mk5
-rw-r--r--drivers/gaudio/pwm/gaudio_play_board_template.h38
-rw-r--r--drivers/gaudio/pwm/gaudio_play_config.h34
-rw-r--r--drivers/gaudio/pwm/gaudio_play_lld.c117
-rw-r--r--drivers/gaudio/pwm/readme.txt12
5 files changed, 206 insertions, 0 deletions
diff --git a/drivers/gaudio/pwm/driver.mk b/drivers/gaudio/pwm/driver.mk
new file mode 100644
index 00000000..52f752aa
--- /dev/null
+++ b/drivers/gaudio/pwm/driver.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gaudio/pwm/gaudio_play_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gaudio/pwm
diff --git a/drivers/gaudio/pwm/gaudio_play_board_template.h b/drivers/gaudio/pwm/gaudio_play_board_template.h
new file mode 100644
index 00000000..24039d17
--- /dev/null
+++ b/drivers/gaudio/pwm/gaudio_play_board_template.h
@@ -0,0 +1,38 @@
+/*
+ * 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
+ */
+
+#ifndef GAUDIO_PLAY_BOARD_H
+#define GAUDIO_PLAY_BOARD_H
+
+/*
+ * This routine is defined in the driver - the timer interrupt should call this routine.
+ *
+ * static void gaudio_play_pwm_timer_callbackI(void);
+ *
+ */
+
+static bool gaudio_play_pwm_setup(uint32_t frequency, ArrayDataFormat format) {
+ /* Initialise the PWM - use a midpoint value for the initial PWM value */
+ /* Initialise the timer interrupt @ frequency */
+ /* Return FALSE if any parameter invalid */
+}
+
+static void gaudio_play_pwm_start(void) {
+ /* Start the PWM */
+ /* Start the timer interrupt */
+}
+
+static void gaudio_play_pwm_stop(void) {
+ /* Stop the timer interrupt */
+ /* Stop the PWM */
+}
+
+static void gaudio_play_pwm_setI(uint16_t value) {
+ /* Set the PWM value */
+}
+
+#endif /* GAUDIO_PLAY_BOARD_H */
diff --git a/drivers/gaudio/pwm/gaudio_play_config.h b/drivers/gaudio/pwm/gaudio_play_config.h
new file mode 100644
index 00000000..9c65cd11
--- /dev/null
+++ b/drivers/gaudio/pwm/gaudio_play_config.h
@@ -0,0 +1,34 @@
+/*
+ * 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
+ */
+
+#ifndef GAUDIO_PLAY_CONFIG_H
+#define GAUDIO_PLAY_CONFIG_H
+
+#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+/* These may need to change for your hardware. If so copy this file to your
+ * project directory and then alter it.
+ * The maximum sample frequency should be less than
+ * Max PWM Clock / (2 ^ Bits per sample)
+ * eg. For the AT91SAM7 max PWM clock = 48MHz / 2
+ * For 10 bit PWM accuracy that means GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY = 23,437 Hz
+ */
+#define GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY 22000
+#define GAUDIO_PLAY_NUM_FORMATS 2
+#define GAUDIO_PLAY_FORMAT1 ARRAY_DATA_10BITUNSIGNED
+#define GAUDIO_PLAY_FORMAT2 ARRAY_DATA_8BITUNSIGNED
+#define GAUDIO_PLAY_NUM_CHANNELS 1
+#define GAUDIO_PLAY_CHANNEL0_IS_STEREO FALSE
+#define GAUDIO_PLAY_MONO 0
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
+
+#endif /* GAUDIO_PLAY_CONFIG_H */
diff --git a/drivers/gaudio/pwm/gaudio_play_lld.c b/drivers/gaudio/pwm/gaudio_play_lld.c
new file mode 100644
index 00000000..07fd14b2
--- /dev/null
+++ b/drivers/gaudio/pwm/gaudio_play_lld.c
@@ -0,0 +1,117 @@
+/*
+ * 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
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY
+
+/* Include the driver defines */
+#include "src/gaudio/driver_play.h"
+
+/* Forward definition */
+static void gaudio_play_pwm_timer_callbackI(void);
+
+/* Include the board interface */
+#include "gaudio_play_board.h"
+
+static GDataBuffer *pplay;
+static ArrayDataFormat playfmt;
+static size_t playlen;
+static uint8_t *pdata;
+
+static void gaudio_play_pwm_timer_callbackI(void) {
+ if (pplay) {
+
+ // Get the next value from the current data buffer
+ if (gfxSampleFormatBits(playfmt) > 8) {
+ gaudio_play_pwm_setI(*(uint16_t *)pdata);
+ pdata += 2;
+ } else {
+ gaudio_play_pwm_setI(*pdata);
+ pdata++;
+ }
+
+ // Are we done yet
+ if (--playlen)
+ return;
+ gaudioPlayReleaseDataBlockI(pplay);
+
+ // Get a new data buffer
+ if (!(pplay = gaudioPlayGetDataBlockI())) {
+ // All is done
+ gaudioPlayDoneI();
+ return;
+ }
+
+ } else {
+ // Get a new data buffer
+ if (!(pplay = gaudioPlayGetDataBlockI()))
+ return;
+ }
+
+ // Set up ready for the new buffer
+ playlen = pplay->len;
+ if (gfxSampleFormatBits(playfmt) > 8)
+ playlen >>= 1;
+ pdata = (uint8_t *)(pplay+1);
+}
+
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
+ (void) channel;
+
+ if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_10BITUNSIGNED)
+ return FALSE;
+
+ playfmt = format;
+ return gaudio_play_pwm_setup(frequency, format);
+}
+
+bool_t gaudio_play_lld_set_volume(uint8_t vol) {
+ (void) vol;
+ return FALSE;
+}
+
+void gaudio_play_lld_start(void) {
+
+ gfxSystemLock();
+ // Get a new data buffer
+ if (pplay || !(pplay = gaudioPlayGetDataBlockI())) {
+ gfxSystemUnlock(); // Nothing to do
+ return;
+ }
+
+ // Set up ready for the new buffer
+ playlen = pplay->len;
+ if (gfxSampleFormatBits(playfmt) > 8)
+ playlen >>= 1;
+ pdata = (uint8_t *)(pplay+1);
+ gfxSystemUnlock();
+
+ // Start the playing
+ gaudio_play_pwm_start();
+}
+
+void gaudio_play_lld_stop(void) {
+ // Stop everything
+ gaudio_play_pwm_stop();
+
+ // We may need to clean up the remaining buffer.
+ gfxSystemLock();
+ if (pplay) {
+ gaudioPlayReleaseDataBlockI(pplay);
+ pplay = 0;
+ gaudioPlayDoneI();
+ }
+ gfxSystemUnlock();
+}
+
+#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
diff --git a/drivers/gaudio/pwm/readme.txt b/drivers/gaudio/pwm/readme.txt
new file mode 100644
index 00000000..1dd3ed9a
--- /dev/null
+++ b/drivers/gaudio/pwm/readme.txt
@@ -0,0 +1,12 @@
+This driver uses a PWM output and a timer to implement an audio play channel.
+
+Whilst the default config settings will probably work for your hardware, you may need to change them.
+If so copy gaudio_play_config.h to your project directory and then alter it.
+
+The maximum sample frequency is governed primarily by the number of bits of resolution and the
+maximum PWM clock rate. The maximum sample frequency should be less than...
+
+ Max PWM Clock / (2 ^ Bits per sample)
+
+eg. For the AT91SAM7 max PWM clock = 48MHz / 2
+ For 10 bit PWM accuracy that means GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY = 23,437 Hz