New PWM audio driver for audio output using a digital pin on a CPU
This commit is contained in:
parent
c16cb15ce9
commit
04f03ea71d
5
drivers/gaudio/pwm/driver.mk
Normal file
5
drivers/gaudio/pwm/driver.mk
Normal file
@ -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
|
38
drivers/gaudio/pwm/gaudio_play_board_template.h
Normal file
38
drivers/gaudio/pwm/gaudio_play_board_template.h
Normal file
@ -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 */
|
34
drivers/gaudio/pwm/gaudio_play_config.h
Normal file
34
drivers/gaudio/pwm/gaudio_play_config.h
Normal file
@ -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 */
|
117
drivers/gaudio/pwm/gaudio_play_lld.c
Normal file
117
drivers/gaudio/pwm/gaudio_play_lld.c
Normal file
@ -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 */
|
12
drivers/gaudio/pwm/readme.txt
Normal file
12
drivers/gaudio/pwm/readme.txt
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user